From 649edf1dd13543acad8a500d11b5c96e086e3595 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 18 Feb 2016 10:26:58 -0700 Subject: [PATCH 01/33] Add g++ 4.9 and 5 to travis ... hopefully --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a53e346..90e5d62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ env: matrix: - GCC_VER="4.6" - GCC_VER="4.8" + - GCC_VER="4.9" + - GCC_VER="5" global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= @@ -13,7 +15,7 @@ env: before_install: - export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" - - if [ "$GCC_VER" = "4.8" ]; then export COVERAGE=1 CPPCHECK=1; fi + - if [ "$GCC_VER" = "5" ]; then export COVERAGE=1 CPPCHECK=1; fi - if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y From 70c6ed713b1d74e6ef42918cab6ac06b8e3d05b9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 09:24:50 -0700 Subject: [PATCH 02/33] Add new compilers and remove deprecated ones --- .decent_ci-Linux.yaml | 17 +++++++++++------ .decent_ci-Windows.yaml | 7 ------- .travis.yml | 1 - 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index dfb5056..9bd1541 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -1,35 +1,40 @@ compilers: - name: "clang" - version: "3.5" + version: "3.6" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON collect_performance_results: true - name: "clang" build_tag: "LibC++" - version: "3.5" + version: "3.6" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON - name: "clang" build_tag: AddressSanitizer - version: "3.6" + version: "3.7" skip_packaging: true cmake_extra_flags: -DRUN_FUZZY_TESTS:BOOL=TRUE -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON - name: "clang" build_tag: ThreadSanitizer - version: "3.6" + version: "3.7" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON - name: "gcc" version: "4.8" + skip_packaging: true + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON + collect_performance_results: true + - name: "gcc" + version: "4.9" build_tag: "NoThreads" cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF collect_performance_results: true - name: "gcc" - version: "4.8" + version: "4.9" cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON collect_performance_results: true - name: "gcc" - version: "4.6" + version: "5" skip_packaging: true cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON collect_performance_results: true diff --git a/.decent_ci-Windows.yaml b/.decent_ci-Windows.yaml index 7f36f91..ea37b1b 100644 --- a/.decent_ci-Windows.yaml +++ b/.decent_ci-Windows.yaml @@ -10,11 +10,4 @@ compilers: cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% compiler_extra_flags: /analyze skip_packaging: true - - name: Visual Studio - version: 12 - cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% - - name: Visual Studio - version: 12 - architecture: Win64 - cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% diff --git a/.travis.yml b/.travis.yml index 90e5d62..2c962bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ compiler: - gcc env: matrix: - - GCC_VER="4.6" - GCC_VER="4.8" - GCC_VER="4.9" - GCC_VER="5" From 463f6889785f42948b94f977f3a7b538fdf8005a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 09:48:35 -0700 Subject: [PATCH 03/33] Update to C++14 compiler flags --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50b5e3e..47a3da1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,13 +148,13 @@ endif() if(CMAKE_COMPILER_IS_GNUCC) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) - if(GCC_VERSION VERSION_LESS 4.8) - set(CPP11_FLAG "-std=c++0x") + if(GCC_VERSION VERSION_LESS 4.9) + set(CPP11_FLAG "-std=c++1y") else() - set(CPP11_FLAG "-std=c++11") + set(CPP11_FLAG "-std=c++14") endif() else() - set(CPP11_FLAG "-std=c++11") + set(CPP11_FLAG "-std=c++14") endif() if(MSVC) From b5b6e5a5a31128761574dc70769112aa6d649608 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 11:15:39 -0700 Subject: [PATCH 04/33] Drop ifdef'd code for gcc4.6 and msvc12 --- CMakeLists.txt | 4 +- include/chaiscript/chaiscript_defines.hpp | 32 +----- include/chaiscript/dispatchkit/any.hpp | 12 +-- .../chaiscript/dispatchkit/bad_boxed_cast.hpp | 8 +- .../chaiscript/dispatchkit/boxed_number.hpp | 7 +- .../chaiscript/dispatchkit/boxed_value.hpp | 37 +++---- .../chaiscript/dispatchkit/dispatchkit.hpp | 35 +++--- .../chaiscript/dispatchkit/dynamic_object.hpp | 2 +- .../dispatchkit/dynamic_object_detail.hpp | 22 ++-- .../dispatchkit/exception_specification.hpp | 10 +- .../dispatchkit/proxy_functions.hpp | 59 +++++----- .../dispatchkit/proxy_functions_detail.hpp | 101 +----------------- .../dispatchkit/type_conversions.hpp | 32 +++--- include/chaiscript/dispatchkit/type_info.hpp | 31 +++--- .../chaiscript/language/chaiscript_common.hpp | 14 +-- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 100 ++++++++--------- include/chaiscript/utility/utility.hpp | 9 -- samples/inheritance.cpp | 4 +- src/test_module.cpp | 16 +-- 20 files changed, 182 insertions(+), 357 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dee4449..33758a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,8 +101,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt") set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt") -set(CPACK_PACKAGE_VERSION_MAJOR 5) -set(CPACK_PACKAGE_VERSION_MINOR 8) +set(CPACK_PACKAGE_VERSION_MAJOR 6) +set(CPACK_PACKAGE_VERSION_MINOR 0) set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index b12347b..6c05594 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -12,17 +12,10 @@ #define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER) #define CHAISCRIPT_MSVC _MSC_VER #define CHAISCRIPT_HAS_DECLSPEC -#if _MSC_VER <= 1800 -#define CHAISCRIPT_MSVC_12 -#endif #else #define CHAISCRIPT_COMPILER_VERSION __VERSION__ #endif -#ifndef CHAISCRIPT_MSVC_12 -#define CHAISCRIPT_HAS_MAGIC_STATICS -#endif - #include #if defined( _LIBCPP_VERSION ) @@ -51,26 +44,15 @@ #endif #endif -#if (defined(CHAISCRIPT_MSVC) && !defined(CHAISCRIPT_MSVC_12)) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP)) -/// Currently only g++>=4.8 supports this natively +#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP)) /// \todo Make this support other compilers when possible #define CHAISCRIPT_HAS_THREAD_LOCAL #endif -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6) -#define CHAISCRIPT_GCC_4_6 -#endif - #if defined(__llvm__) #define CHAISCRIPT_CLANG #endif -#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG) -#define CHAISCRIPT_OVERRIDE override -#else -#define CHAISCRIPT_OVERRIDE -#endif - #ifdef CHAISCRIPT_HAS_DECLSPEC #define CHAISCRIPT_MODULE_EXPORT extern "C" __declspec(dllexport) @@ -78,14 +60,6 @@ #define CHAISCRIPT_MODULE_EXPORT extern "C" #endif -#ifdef CHAISCRIPT_MSVC_12 -#define CHAISCRIPT_NOEXCEPT throw() -#define CHAISCRIPT_CONSTEXPR -#else -#define CHAISCRIPT_NOEXCEPT noexcept -#define CHAISCRIPT_CONSTEXPR constexpr -#endif - #ifdef _DEBUG #define CHAISCRIPT_DEBUG true #else @@ -95,8 +69,8 @@ #include namespace chaiscript { - static const int version_major = 5; - static const int version_minor = 8; + static const int version_major = 6; + static const int version_minor = 0; static const int version_patch = 0; static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index e86ba0e..c9b62a1 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -21,17 +21,17 @@ namespace chaiscript { class bad_any_cast : public std::bad_cast { public: - bad_any_cast() CHAISCRIPT_NOEXCEPT + bad_any_cast() noexcept : m_what("bad any cast") { } bad_any_cast(const bad_any_cast &) = default; - virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {} + virtual ~bad_any_cast() noexcept {} /// \brief Description of what error occurred - virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE + virtual const char * what() const noexcept override { return m_what.c_str(); } @@ -76,12 +76,12 @@ namespace chaiscript { virtual ~Data_Impl() {} - virtual void *data() CHAISCRIPT_OVERRIDE + virtual void *data() override { return &m_data; } - std::unique_ptr clone() const CHAISCRIPT_OVERRIDE + std::unique_ptr clone() const override { return std::unique_ptr(new Data_Impl(m_data)); } @@ -107,10 +107,8 @@ namespace chaiscript { } } -#if !defined(_MSC_VER) || _MSC_VER != 1800 Any(Any &&) = default; Any &operator=(Any &&t_any) = default; -#endif template::type>::value>::type> diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index 0716749..44cbf25 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -30,7 +30,7 @@ namespace chaiscript { public: bad_boxed_cast(Type_Info t_from, const std::type_info &t_to, - std::string t_what) CHAISCRIPT_NOEXCEPT + std::string t_what) noexcept : from(std::move(t_from)), to(&t_to), m_what(std::move(t_what)) { } @@ -40,16 +40,16 @@ namespace chaiscript { } - explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT + explicit bad_boxed_cast(std::string t_what) noexcept : to(nullptr), m_what(std::move(t_what)) { } bad_boxed_cast(const bad_boxed_cast &) = default; - virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {} + virtual ~bad_boxed_cast() noexcept {} /// \brief Description of what error occurred - virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE + virtual const char * what() const noexcept override { return m_what.c_str(); } diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 8a784ec..6d1a146 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -30,7 +30,7 @@ namespace chaiscript { arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {} arithmetic_error(const arithmetic_error &) = default; - virtual ~arithmetic_error() CHAISCRIPT_NOEXCEPT {} + virtual ~arithmetic_error() noexcept {} }; } } @@ -90,7 +90,7 @@ namespace chaiscript { } - static CHAISCRIPT_CONSTEXPR Common_Types get_common_type(size_t t_size, bool t_signed) + static constexpr Common_Types get_common_type(size_t t_size, bool t_signed) { return (t_size == 1 && t_signed)?(Common_Types::t_int8) :(t_size == 1)?(Common_Types::t_uint8) @@ -508,11 +508,8 @@ namespace chaiscript } Boxed_Number(const Boxed_Number &) = default; - -#if !defined(_MSC_VER) || _MSC_VER != 1800 Boxed_Number(Boxed_Number &&) = default; Boxed_Number& operator=(Boxed_Number &&) = default; -#endif template explicit Boxed_Number(T t) : bv(Boxed_Value(t)) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 5a49119..70bfe12 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -62,10 +62,8 @@ namespace chaiscript Data(const Data &) = delete; -#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800) Data(Data &&) = default; Data &operator=(Data &&rhs) = default; -#endif Type_Info m_type_info; @@ -189,11 +187,8 @@ namespace chaiscript { } -#if !defined(_MSC_VER) || _MSC_VER != 1800 Boxed_Value(Boxed_Value&&) = default; Boxed_Value& operator=(Boxed_Value&&) = default; -#endif - Boxed_Value(const Boxed_Value&) = default; Boxed_Value& operator=(const Boxed_Value&) = default; @@ -210,63 +205,63 @@ namespace chaiscript return *this; } - const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT + const Type_Info &get_type_info() const noexcept { return m_data->m_type_info; } /// return true if the object is uninitialized - bool is_undef() const CHAISCRIPT_NOEXCEPT + bool is_undef() const noexcept { return m_data->m_type_info.is_undef(); } - bool is_const() const CHAISCRIPT_NOEXCEPT + bool is_const() const noexcept { return m_data->m_type_info.is_const(); } - bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool is_type(const Type_Info &ti) const noexcept { return m_data->m_type_info.bare_equal(ti); } - bool is_null() const CHAISCRIPT_NOEXCEPT + bool is_null() const noexcept { return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr); } - const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT + const chaiscript::detail::Any & get() const noexcept { return m_data->m_obj; } - bool is_ref() const CHAISCRIPT_NOEXCEPT + bool is_ref() const noexcept { return m_data->m_is_ref; } - bool is_return_value() const CHAISCRIPT_NOEXCEPT + bool is_return_value() const noexcept { return m_data->m_return_value; } - void reset_return_value() const CHAISCRIPT_NOEXCEPT + void reset_return_value() const noexcept { m_data->m_return_value = false; } - bool is_pointer() const CHAISCRIPT_NOEXCEPT + bool is_pointer() const noexcept { return !is_ref(); } - void *get_ptr() const CHAISCRIPT_NOEXCEPT + void *get_ptr() const noexcept { return m_data->m_data_ptr; } - const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT + const void *get_const_ptr() const noexcept { return m_data->m_const_data_ptr; } @@ -306,7 +301,7 @@ namespace chaiscript /// \returns true if the two Boxed_Values share the same internal type - static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT + static bool type_match(const Boxed_Value &l, const Boxed_Value &r) noexcept { return l.get_type_info() == r.get_type_info(); } @@ -416,10 +411,9 @@ namespace chaiscript return detail::const_var_impl(t); } -#ifdef CHAISCRIPT_HAS_MAGIC_STATICS inline Boxed_Value const_var(bool b) { - static auto t = detail::const_var_impl(true); - static auto f = detail::const_var_impl(false); + static const auto t = detail::const_var_impl(true); + static const auto f = detail::const_var_impl(false); if (b) { return t; @@ -427,7 +421,6 @@ namespace chaiscript return f; } } -#endif } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index c4d6b28..2cc5a70 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -56,14 +56,14 @@ namespace chaiscript class reserved_word_error : public std::runtime_error { public: - reserved_word_error(const std::string &t_word) CHAISCRIPT_NOEXCEPT + reserved_word_error(const std::string &t_word) noexcept : std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word) { } reserved_word_error(const reserved_word_error &) = default; - virtual ~reserved_word_error() CHAISCRIPT_NOEXCEPT {} + virtual ~reserved_word_error() noexcept {} std::string word() const { @@ -78,14 +78,14 @@ namespace chaiscript class illegal_name_error : public std::runtime_error { public: - illegal_name_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT + illegal_name_error(const std::string &t_name) noexcept : std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name) { } illegal_name_error(const illegal_name_error &) = default; - virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {} + virtual ~illegal_name_error() noexcept {} std::string name() const { @@ -101,14 +101,14 @@ namespace chaiscript class name_conflict_error : public std::runtime_error { public: - name_conflict_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT + name_conflict_error(const std::string &t_name) noexcept : std::runtime_error("Name already exists in current context " + t_name), m_name(t_name) { } name_conflict_error(const name_conflict_error &) = default; - virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {} + virtual ~name_conflict_error() noexcept {} std::string name() const { @@ -125,13 +125,13 @@ namespace chaiscript class global_non_const : public std::runtime_error { public: - global_non_const() CHAISCRIPT_NOEXCEPT + global_non_const() noexcept : std::runtime_error("a global object must be const") { } global_non_const(const global_non_const &) = default; - virtual ~global_non_const() CHAISCRIPT_NOEXCEPT {} + virtual ~global_non_const() noexcept {} }; } @@ -276,7 +276,7 @@ namespace chaiscript { } - virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const override { try { const auto &dispatch_fun = dynamic_cast(rhs); @@ -288,7 +288,7 @@ namespace chaiscript virtual ~Dispatch_Function() {} - virtual std::vector get_contained_functions() const CHAISCRIPT_OVERRIDE + virtual std::vector get_contained_functions() const override { return std::vector(m_funcs.begin(), m_funcs.end()); } @@ -314,19 +314,19 @@ namespace chaiscript return arity; } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return std::any_of(m_funcs.cbegin(), m_funcs.cend(), [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return "Multiple method dispatch function wrapper."; } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return dispatch::dispatch(m_funcs, params, t_conversions); } @@ -1332,13 +1332,8 @@ namespace chaiscript const auto lhssize = lhsparamtypes.size(); const auto rhssize = rhsparamtypes.size(); -#ifdef CHAISCRIPT_HAS_MAGIC_STATICS - static auto boxed_type = user_type(); - static auto boxed_pod_type = user_type(); -#else - auto boxed_type = user_type(); - auto boxed_pod_type = user_type(); -#endif + static const auto boxed_type = user_type(); + static const auto boxed_pod_type = user_type(); for (size_t i = 1; i < lhssize && i < rhssize; ++i) { diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 05fc069..d6052d9 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -33,7 +33,7 @@ namespace chaiscript option_explicit_set(const option_explicit_set &) = default; - virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {} + virtual ~option_explicit_set() noexcept {} }; class Dynamic_Object diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index 8c9b8f6..28df3e9 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -72,7 +72,7 @@ namespace chaiscript Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete; Dynamic_Object_Function(Dynamic_Object_Function &) = delete; - virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &f) const override { if (const auto *df = dynamic_cast(&f)) { @@ -82,9 +82,9 @@ namespace chaiscript } } - virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; } + virtual bool is_attribute_function() const override { return m_is_attribute; } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) { @@ -94,19 +94,19 @@ namespace chaiscript } } - virtual std::vector get_contained_functions() const CHAISCRIPT_OVERRIDE + virtual std::vector get_contained_functions() const override { return {m_func}; } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return m_func->annotation(); } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions)) { @@ -116,7 +116,7 @@ namespace chaiscript } } - virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override { return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions); } @@ -210,13 +210,13 @@ namespace chaiscript virtual ~Dynamic_Object_Constructor() {} - virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &f) const override { const Dynamic_Object_Constructor *dc = dynamic_cast(&f); return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { std::vector new_vals{Boxed_Value(Dynamic_Object(m_type_name))}; new_vals.insert(new_vals.end(), vals.begin(), vals.end()); @@ -224,13 +224,13 @@ namespace chaiscript return m_func->call_match(new_vals, t_conversions); } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return m_func->annotation(); } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { auto bv = Boxed_Value(Dynamic_Object(m_type_name), true); std::vector new_params{bv}; diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 55398f7..1b4384b 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -43,7 +43,7 @@ namespace chaiscript { virtual ~Exception_Handler_Impl1() {} - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE + virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { throw_type(bv, t_engine); } @@ -53,7 +53,7 @@ namespace chaiscript { virtual ~Exception_Handler_Impl2() {} - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE + virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { throw_type(bv, t_engine); throw_type(bv, t_engine); @@ -65,7 +65,7 @@ namespace chaiscript { virtual ~Exception_Handler_Impl3() {} - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE + virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { throw_type(bv, t_engine); throw_type(bv, t_engine); @@ -77,7 +77,7 @@ namespace chaiscript { virtual ~Exception_Handler_Impl4() {} - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE + virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { throw_type(bv, t_engine); throw_type(bv, t_engine); @@ -90,7 +90,7 @@ namespace chaiscript { virtual ~Exception_Handler_Impl5() {} - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) CHAISCRIPT_OVERRIDE + virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { throw_type(bv, t_engine); throw_type(bv, t_engine); diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 6128b33..abf5a33 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -282,13 +282,13 @@ namespace chaiscript class guard_error : public std::runtime_error { public: - guard_error() CHAISCRIPT_NOEXCEPT + guard_error() noexcept : std::runtime_error("Guard evaluation failed") { } guard_error(const guard_error &) = default; - virtual ~guard_error() CHAISCRIPT_NOEXCEPT + virtual ~guard_error() noexcept { } }; } @@ -316,7 +316,7 @@ namespace chaiscript virtual ~Dynamic_Proxy_Function() {} - virtual bool operator==(const Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &rhs) const override { const Dynamic_Proxy_Function *prhs = dynamic_cast(&rhs); @@ -327,7 +327,7 @@ namespace chaiscript && this->m_param_types == prhs->m_param_types); } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions))) && test_guard(vals, t_conversions); @@ -344,7 +344,7 @@ namespace chaiscript return m_parsenode; } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return m_description; } @@ -419,7 +419,7 @@ namespace chaiscript protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { if (call_match(params, t_conversions) && test_guard(params, t_conversions)) { @@ -462,19 +462,19 @@ namespace chaiscript assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast(m_args.size())); } - virtual bool operator==(const Proxy_Function_Base &t_f) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &t_f) const override { return &t_f == this; } virtual ~Bound_Function() {} - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return m_f->call_match(build_param_list(vals), t_conversions); } - virtual std::vector get_contained_functions() const CHAISCRIPT_OVERRIDE + virtual std::vector get_contained_functions() const override { return std::vector{m_f}; } @@ -511,7 +511,7 @@ namespace chaiscript return args; } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return "Bound: " + m_f->annotation(); } @@ -527,15 +527,8 @@ namespace chaiscript std::vector types = t_f->get_param_types(); assert(types.size() == t_args.size() + 1); -#ifdef CHAISCRIPT_MSVC_12 -#pragma warning(push) -#pragma warning(disable : 6011) -#endif // this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14 std::vector retval{types[0]}; -#ifdef CHAISCRIPT_MSVC_12 -#pragma warning(pop) -#endif for (size_t i = 0; i < types.size() - 1; ++i) { @@ -548,7 +541,7 @@ namespace chaiscript return retval; } - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return (*m_f)(build_param_list(params), t_conversions); } @@ -568,12 +561,12 @@ namespace chaiscript virtual ~Proxy_Function_Impl_Base() {} - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return ""; } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return static_cast(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions)); } @@ -596,19 +589,19 @@ namespace chaiscript virtual ~Proxy_Function_Callable_Impl() {} - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } - virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &t_func) const override { return dynamic_cast *>(&t_func) != nullptr; } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { typedef typename detail::Function_Signature::Return_Type Return_Type; return detail::Do_Call::template go(m_f, params, t_conversions); @@ -648,12 +641,12 @@ namespace chaiscript virtual ~Assignable_Proxy_Function_Impl() {} - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } - virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &t_func) const override { return dynamic_cast *>(&t_func) != nullptr; } @@ -663,12 +656,12 @@ namespace chaiscript return m_f.get(); } - virtual void assign(const std::shared_ptr &t_rhs) CHAISCRIPT_OVERRIDE { + virtual void assign(const std::shared_ptr &t_rhs) override { m_f.get() = dispatch::functor(t_rhs, nullptr); } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return detail::Do_Call::result_type>::template go(m_f.get(), params, t_conversions); } @@ -691,9 +684,9 @@ namespace chaiscript virtual ~Attribute_Access() {} - virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return true; } + virtual bool is_attribute_function() const override { return true; } - virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE + virtual bool operator==(const Proxy_Function_Base &t_func) const override { const Attribute_Access * aa = dynamic_cast *>(&t_func); @@ -705,7 +698,7 @@ namespace chaiscript } } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &) const override { if (vals.size() != 1) { @@ -715,13 +708,13 @@ namespace chaiscript return vals[0].get_type_info().bare_equal(user_type()); } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE + virtual std::string annotation() const override { return ""; } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { const Boxed_Value &bv = params[0]; if (bv.is_const()) @@ -769,7 +762,7 @@ namespace chaiscript dispatch_error(const dispatch_error &) = default; - virtual ~dispatch_error() CHAISCRIPT_NOEXCEPT {} + virtual ~dispatch_error() noexcept {} std::vector parameters; std::vector functions; diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 452a999..c4d30ff 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -43,7 +43,7 @@ namespace chaiscript arity_error(const arity_error &) = default; - virtual ~arity_error() CHAISCRIPT_NOEXCEPT {} + virtual ~arity_error() noexcept {} int got; int expected; @@ -66,103 +66,6 @@ namespace chaiscript } -#ifdef CHAISCRIPT_GCC_4_6 - /// \todo REMOVE THIS WHEN WE DROP G++4.6 - - - // Forward declaration - template - struct Try_Cast; - - template - struct Try_Cast - { - static void do_try(const std::vector ¶ms, size_t generation, const Type_Conversions_State &t_conversions) - { - boxed_cast(params[generation], &t_conversions); - Try_Cast::do_try(params, generation+1, t_conversions); - } - }; - - // 0th case - template<> - struct Try_Cast<> - { - static void do_try(const std::vector &, size_t, const Type_Conversions_State &) - { - } - }; - - - /** - * Used by Proxy_Function_Impl to determine if it is equivalent to another - * Proxy_Function_Impl object. This function is primarily used to prevent - * registration of two functions with the exact same signatures - */ - template - bool compare_types_cast(Ret (*)(Params...), - const std::vector ¶ms, const Type_Conversions_State &t_conversions) - { - try { - Try_Cast::do_try(params, 0, t_conversions); - } catch (const exception::bad_boxed_cast &) { - return false; - } - - return true; - } - - template - struct Call_Func - { - - template - static Ret do_call(const Callable &f, - const std::vector ¶ms, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams) - { - return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); - } - }; - - template - struct Call_Func - { -#ifdef CHAISCRIPT_MSVC -#pragma warning(push) -#pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this -#endif - template - static Ret do_call(const Callable &f, - const std::vector &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams) - { - return f(boxed_cast(std::forward(innerparams), &t_conversions)...); - } -#ifdef CHAISCRIPT_MSVC -#pragma warning(pop) -#endif - }; - - /** - * Used by Proxy_Function_Impl to perform typesafe execution of a function. - * The function attempts to unbox each parameter to the expected type. - * if any unboxing fails the execution of the function fails and - * the bad_boxed_cast is passed up to the caller. - */ - template - Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, const Callable &f, - const std::vector ¶ms, const Type_Conversions_State &t_conversions) - { - if (params.size() == sizeof...(Params)) - { - return Call_Func::do_call(f, params, t_conversions); - } - - throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); - } - - - -#else template struct Indexes @@ -234,8 +137,6 @@ namespace chaiscript return call_func(sig, indexes(), f, params, t_conversions); } -#endif - } } diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3a4d239..122f74d 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -29,48 +29,48 @@ namespace chaiscript { public: bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to, - const std::string &t_what) CHAISCRIPT_NOEXCEPT + const std::string &t_what) noexcept : bad_boxed_cast(t_from, t_to, t_what) { } - bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT + bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept : bad_boxed_cast(t_from, t_to) { } - bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT + bad_boxed_dynamic_cast(const std::string &w) noexcept : bad_boxed_cast(w) { } bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default; - virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {} + virtual ~bad_boxed_dynamic_cast() noexcept {} }; class bad_boxed_type_cast : public bad_boxed_cast { public: bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to, - const std::string &t_what) CHAISCRIPT_NOEXCEPT + const std::string &t_what) noexcept : bad_boxed_cast(t_from, t_to, t_what) { } - bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT + bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) noexcept : bad_boxed_cast(t_from, t_to) { } - bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT + bad_boxed_type_cast(const std::string &w) noexcept : bad_boxed_cast(w) { } bad_boxed_type_cast(const bad_boxed_type_cast &) = default; - virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {} + virtual ~bad_boxed_type_cast() noexcept {} }; } @@ -242,12 +242,12 @@ namespace chaiscript { } - virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value convert_down(const Boxed_Value &t_base) const override { return Dynamic_Caster::cast(t_base); } - virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value convert(const Boxed_Value &t_derived) const override { return Static_Caster::cast(t_derived); } @@ -262,17 +262,17 @@ namespace chaiscript { } - virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value convert_down(const Boxed_Value &t_base) const override { throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types"); } - virtual bool bidir() const CHAISCRIPT_OVERRIDE + virtual bool bidir() const override { return false; } - virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value convert(const Boxed_Value &t_derived) const override { return Static_Caster::cast(t_derived); } @@ -290,18 +290,18 @@ namespace chaiscript { } - virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value convert_down(const Boxed_Value &) const override { throw chaiscript::exception::bad_boxed_type_cast("No conversion exists"); } - virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value convert(const Boxed_Value &t_from) const override { /// \todo better handling of errors from the conversion function return m_func(t_from); } - virtual bool bidir() const CHAISCRIPT_OVERRIDE + virtual bool bidir() const override { return false; } diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index c91a444..f1f54cb 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -29,7 +29,7 @@ namespace chaiscript class Type_Info { public: - CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + constexpr Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) : m_type_info(t_ti), m_bare_type_info(t_bare_ti), m_flags((static_cast(t_is_const) << is_const_flag) @@ -40,55 +40,52 @@ namespace chaiscript { } - CHAISCRIPT_CONSTEXPR Type_Info() + constexpr Type_Info() : m_type_info(nullptr), m_bare_type_info(nullptr), m_flags(1 << is_undef_flag) { } -#if !defined(_MSC_VER) || _MSC_VER != 1800 Type_Info(Type_Info&&) = default; Type_Info& operator=(Type_Info&&) = default; -#endif - Type_Info(const Type_Info&) = default; Type_Info& operator=(const Type_Info&) = default; - CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + constexpr bool operator<(const Type_Info &ti) const noexcept { return m_type_info < ti.m_type_info; } - CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + constexpr bool operator==(const Type_Info &ti) const noexcept { return ti.m_type_info == m_type_info || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); } - CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + constexpr bool operator==(const std::type_info &ti) const noexcept { return m_type_info != nullptr && (*m_type_info) == ti; } - CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + constexpr bool bare_equal(const Type_Info &ti) const noexcept { return ti.m_bare_type_info == m_bare_type_info || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); } - CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT + constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept { return m_bare_type_info != nullptr && (*m_bare_type_info) == ti; } - CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_const_flag)) != 0; } - CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_reference_flag)) != 0; } - CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_void_flag)) != 0; } - CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_arithmetic_flag)) != 0; } - CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_undef_flag)) != 0; } - CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return (m_flags & (1 << is_pointer_flag)) != 0; } + constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; } + constexpr bool is_reference() const noexcept { return (m_flags & (1 << is_reference_flag)) != 0; } + constexpr bool is_void() const noexcept { return (m_flags & (1 << is_void_flag)) != 0; } + constexpr bool is_arithmetic() const noexcept { return (m_flags & (1 << is_arithmetic_flag)) != 0; } + constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; } + constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; } std::string name() const { @@ -110,7 +107,7 @@ namespace chaiscript } } - CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const + constexpr const std::type_info *bare_type_info() const { return m_bare_type_info; } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index b44a5a3..27ac85f 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -113,7 +113,7 @@ namespace chaiscript eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, const std::vector &t_parameters, const std::vector &t_functions, bool t_dot_notation, - const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT : + const chaiscript::detail::Dispatch_Engine &t_ss) noexcept : std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_dot_notation, t_ss)), reason(t_why), start_position(t_where), filename(t_fname), detail(format_detail(t_functions, t_dot_notation, t_ss)) {} @@ -121,18 +121,18 @@ namespace chaiscript eval_error(const std::string &t_why, const std::vector &t_parameters, const std::vector &t_functions, bool t_dot_notation, - const chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_NOEXCEPT : + const chaiscript::detail::Dispatch_Engine &t_ss) noexcept : std::runtime_error(format(t_why, t_parameters, t_dot_notation, t_ss)), reason(t_why), detail(format_detail(t_functions, t_dot_notation, t_ss)) {} - eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) CHAISCRIPT_NOEXCEPT : + eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) noexcept : std::runtime_error(format(t_why, t_where, t_fname)), reason(t_why), start_position(t_where), filename(t_fname) {} - eval_error(const std::string &t_why) CHAISCRIPT_NOEXCEPT + eval_error(const std::string &t_why) noexcept : std::runtime_error("Error: \"" + t_why + "\" "), reason(t_why) {} @@ -161,7 +161,7 @@ namespace chaiscript return ss.str(); } - virtual ~eval_error() CHAISCRIPT_NOEXCEPT {} + virtual ~eval_error() noexcept {} private: @@ -420,12 +420,12 @@ namespace chaiscript /// Errors generated when loading a file struct file_not_found_error : std::runtime_error { - file_not_found_error(const std::string &t_filename) CHAISCRIPT_NOEXCEPT + file_not_found_error(const std::string &t_filename) noexcept : std::runtime_error("File Not Found: " + t_filename) { } file_not_found_error(const file_not_found_error &) = default; - virtual ~file_not_found_error() CHAISCRIPT_NOEXCEPT {} + virtual ~file_not_found_error() noexcept {} }; } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index f6e9b56..78d86ee 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -54,13 +54,13 @@ namespace chaiscript /// \brief Thrown if an error occurs while attempting to load a binary module struct load_module_error : std::runtime_error { - load_module_error(const std::string &t_reason) CHAISCRIPT_NOEXCEPT + load_module_error(const std::string &t_reason) noexcept : std::runtime_error(t_reason) { } load_module_error(const load_module_error &) = default; - virtual ~load_module_error() CHAISCRIPT_NOEXCEPT {} + virtual ~load_module_error() noexcept {} }; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 60474b4..7c4c77c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -89,13 +89,13 @@ namespace chaiscript { } virtual ~Binary_Operator_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { auto lhs = this->children[0]->eval(t_ss); auto rhs = this->children[1]->eval(t_ss); return do_oper(t_ss, m_oper, text, lhs, rhs); } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")"; } @@ -137,7 +137,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)), m_value(std::move(t_bv)) { assert(text != ""); } virtual ~Int_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ return m_value; } @@ -152,7 +152,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Float, std::move(t_loc)), m_value(std::move(t_bv)) { } virtual ~Float_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ return m_value; } @@ -169,7 +169,7 @@ namespace chaiscript { } virtual ~Id_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (!m_value.is_undef()) { return m_value; @@ -226,7 +226,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Eol, std::move(t_loc)) { } virtual ~Eol_AST_Node() {} - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "\n"; } @@ -238,7 +238,7 @@ namespace chaiscript Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } virtual ~Fun_Call_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params; @@ -278,7 +278,7 @@ namespace chaiscript } } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { std::ostringstream oss; @@ -308,7 +308,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } virtual ~Arg_AST_Node() {} - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { std::ostringstream oss; for (size_t j = 0; j < this->children.size(); ++j) { @@ -330,7 +330,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } virtual ~Arg_List_AST_Node() {} - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { std::ostringstream oss; for (size_t j = 0; j < this->children.size(); ++j) { @@ -401,7 +401,7 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_clone_loc; virtual ~Equation_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); Boxed_Value rhs = this->children[2]->eval(t_ss); Boxed_Value lhs = this->children[0]->eval(t_ss); @@ -476,7 +476,7 @@ namespace chaiscript Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { } virtual ~Global_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const std::string &idname = [&]()->const std::string &{ @@ -503,7 +503,7 @@ namespace chaiscript Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { } virtual ~Var_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (this->children[0]->identifier == AST_Node_Type::Reference) { return this->children[0]->eval(t_ss); @@ -524,7 +524,7 @@ namespace chaiscript } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "var " + this->children[0]->text; } @@ -537,7 +537,7 @@ namespace chaiscript Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } virtual ~Array_Call_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; @@ -552,7 +552,7 @@ namespace chaiscript } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { std::ostringstream oss; oss << this->children[0]->pretty_print(); @@ -579,7 +579,7 @@ namespace chaiscript children[2]->children[0]->text:children[2]->text) { } virtual ~Dot_Access_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); @@ -636,11 +636,11 @@ namespace chaiscript m_value(const_var(text)) { } virtual ~Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override { return m_value; } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "\"" + text + "\""; } @@ -657,11 +657,11 @@ namespace chaiscript m_value(const_var(char(text.at(0)))) { } virtual ~Single_Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ return m_value; } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "'" + text + "'"; } @@ -678,7 +678,7 @@ namespace chaiscript virtual ~Lambda_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ const auto captures = [&]()->std::map{ std::map named_captures; @@ -717,7 +717,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { } virtual ~Block_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); const auto num_children = children.size(); @@ -735,7 +735,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } virtual ~Def_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ std::vector t_param_names; size_t numparams = 0; AST_NodePtr guardnode; @@ -799,7 +799,7 @@ namespace chaiscript While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { } virtual ~While_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -825,7 +825,7 @@ namespace chaiscript Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { } virtual ~Class_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); /// \todo do this better @@ -844,7 +844,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } virtual ~Ternary_Cond_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (get_bool_condition(children[0]->eval(t_ss))) { return children[1]->eval(t_ss); } @@ -860,7 +860,7 @@ namespace chaiscript If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { } virtual ~If_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ if (get_bool_condition(children[0]->eval(t_ss))) { return children[1]->eval(t_ss); @@ -893,7 +893,7 @@ namespace chaiscript { assert(children.size() == 4); } virtual ~For_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -925,7 +925,7 @@ namespace chaiscript Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } virtual ~Switch_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { bool breaking = false; size_t currentCase = 1; bool hasMatched = false; @@ -971,7 +971,7 @@ namespace chaiscript { assert(children.size() == 2); /* how many children does it have? */ } virtual ~Case_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); children[1]->eval(t_ss); @@ -986,7 +986,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } virtual ~Default_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); children[0]->eval(t_ss); @@ -1001,7 +1001,7 @@ namespace chaiscript Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } virtual ~Inline_Array_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { std::vector vec; if (!children.empty()) { @@ -1022,7 +1022,7 @@ namespace chaiscript } } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "[" + AST_Node::pretty_print() + "]"; } @@ -1035,7 +1035,7 @@ namespace chaiscript Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } virtual ~Inline_Map_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { std::map retval; @@ -1063,7 +1063,7 @@ namespace chaiscript Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { } virtual ~Return_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ if (!this->children.empty()) { throw detail::Return_Value(children[0]->eval(t_ss)); } @@ -1079,7 +1079,7 @@ namespace chaiscript File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } virtual ~File_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { const auto num_children = children.size(); @@ -1105,7 +1105,7 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { Boxed_Value bv; t_ss.add_object(this->children[0]->text, bv); @@ -1127,7 +1127,7 @@ namespace chaiscript { } virtual ~Prefix_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ Boxed_Value bv(children[1]->eval(t_ss)); try { @@ -1155,7 +1155,7 @@ namespace chaiscript Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } virtual ~Break_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Break_Loop(); } }; @@ -1165,7 +1165,7 @@ namespace chaiscript Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { } virtual ~Continue_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Continue_Loop(); } }; @@ -1178,7 +1178,7 @@ namespace chaiscript { } virtual ~Noop_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ // It's a no-op, that evaluates to "true" return m_value; } @@ -1206,7 +1206,7 @@ namespace chaiscript Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } virtual ~Inline_Range_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { auto oper1 = children[0]->children[0]->children[0]->eval(t_ss); auto oper2 = children[0]->children[0]->children[1]->eval(t_ss); @@ -1294,7 +1294,7 @@ namespace chaiscript return retval; } - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ Boxed_Value retval; chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1357,7 +1357,7 @@ namespace chaiscript Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } virtual ~Method_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ AST_NodePtr guardnode; @@ -1448,7 +1448,7 @@ namespace chaiscript Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { } virtual ~Attr_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const auto &d = t_ss->get_parent_locals(); const auto itr = d.find("_current_class_name"); @@ -1487,12 +1487,12 @@ namespace chaiscript { assert(children.size() == 3); } virtual ~Logical_And_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ return const_var(get_bool_condition(children[0]->eval(t_ss)) && get_bool_condition(children[2]->eval(t_ss))); } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "(" + AST_Node::pretty_print() + ")"; } @@ -1504,12 +1504,12 @@ namespace chaiscript AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } virtual ~Logical_Or_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ return const_var(get_bool_condition(children[0]->eval(t_ss)) || get_bool_condition(children[2]->eval(t_ss))); } - virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE + virtual std::string pretty_print() const override { return "(" + AST_Node::pretty_print() + ")"; } diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 22ab8e9..17950e2 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -69,11 +69,7 @@ namespace chaiscript typename std::enable_if::value, void>::type add_class(ModuleType &t_module, const std::string &t_class_name, -#ifdef CHAISCRIPT_GCC_4_6 - const std::vector> &t_constants -#else const std::vector::type, std::string>> &t_constants -#endif ) { t_module.add(chaiscript::user_type(), t_class_name); @@ -87,13 +83,8 @@ namespace chaiscript return assign(not_equal(equal())); }()); -#ifdef CHAISCRIPT_GCC_4_6 t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "=="); t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "=="); -#else - t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type::type &i) { return e == i; }), "=="); - t_module.add(chaiscript::fun([](const typename std::underlying_type::type &i, const Enum &e) { return i == e; }), "=="); -#endif for (const auto &constant : t_constants) { diff --git a/samples/inheritance.cpp b/samples/inheritance.cpp index e8ef192..133feb9 100644 --- a/samples/inheritance.cpp +++ b/samples/inheritance.cpp @@ -44,14 +44,14 @@ class ChaiScriptDerived : public BaseClass tie(t_funcs.at(1), m_validateValueImpl); } - std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE + std::string doSomething(float f, double d) const override { assert(m_doSomethingImpl); return m_doSomethingImpl(*this, f, d); } protected: - bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE + bool validateValue(const std::string &t_val) override { assert(m_validateValueImpl); return m_validateValueImpl(*this, t_val); diff --git a/src/test_module.cpp b/src/test_module.cpp index ebccf73..b0ce5ae 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -8,17 +8,9 @@ class TestBaseType { public: -#ifdef CHAISCRIPT_MSVC_12 -#pragma warning(push) -#pragma warning(disable : 4351) -#endif - // MSVC 12 warns that we are using new (correct) behavior TestBaseType() : val(10), const_val(15), mdarray{} { } TestBaseType(int) : val(10), const_val(15), mdarray{} { } TestBaseType(int *) : val(10), const_val(15), mdarray{} { } -#ifdef CHAISCRIPT_MSVC_12 -#pragma warning(pop) -#endif TestBaseType(const TestBaseType &) = default; virtual ~TestBaseType() {} @@ -84,7 +76,7 @@ class TestDerivedType : public TestBaseType virtual ~TestDerivedType() {} TestDerivedType(const TestDerivedType &) = default; TestDerivedType() = default; - virtual int func() CHAISCRIPT_OVERRIDE { return 1; } + virtual int func() override { return 1; } int derived_only_func() { return 19; } private: @@ -179,16 +171,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func"); m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val"); -#ifndef CHAISCRIPT_MSVC_12 - // we cannot support these in MSVC_12 because of a bug in the implementation of - // std::reference_wrapper - // Array types m->add(chaiscript::fun(&TestBaseType::mdarray), "mdarray"); m->add(chaiscript::bootstrap::array("IntArray_2_3_5")); m->add(chaiscript::bootstrap::array("IntArray_3_5")); m->add(chaiscript::bootstrap::array("IntArray_5")); - // end array types -#endif // member that is a function m->add(chaiscript::fun(&TestBaseType::func_member), "func_member"); From 33e27b4f852b95f62383fe9632d25352274a264d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 13:48:20 -0700 Subject: [PATCH 05/33] Reorganize builds run on decent_ci --- .decent_ci-Linux.yaml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index d0ae93d..4d777eb 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -11,14 +11,24 @@ compilers: cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON - name: "clang" build_tag: AddressSanitizer - version: "3.7" + version: "3.6" skip_packaging: true cmake_extra_flags: -DRUN_FUZZY_TESTS:BOOL=TRUE -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON - name: "clang" build_tag: ThreadSanitizer - version: "3.7" + version: "3.6" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON + - name: "clang" + version: "3.7" + skip_packaging: true + cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON + collect_performance_results: true + - name: "clang" + build_tag: "LibC++" + version: "3.7" + skip_packaging: true + cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON - name: "gcc" version: "4.8" skip_packaging: true @@ -26,12 +36,12 @@ compilers: collect_performance_results: true - name: "gcc" version: "4.9" - build_tag: "NoThreads" - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON collect_performance_results: true - name: "gcc" version: "4.9" - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON + build_tag: "NoThreads" + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF collect_performance_results: true - name: "gcc" version: "5" From 457367ea7b32a725577fa65237bc68bcd69f4fcc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 14:31:19 -0700 Subject: [PATCH 06/33] Add failing tests for locale changes re #250 --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- unittests/compiled_tests.cpp | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2258af1..31452ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 5) set(CPACK_PACKAGE_VERSION_MINOR 8) -set(CPACK_PACKAGE_VERSION_PATCH 0) +set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index b12347b..cf2a5a6 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -97,7 +97,7 @@ namespace chaiscript { static const int version_major = 5; static const int version_minor = 8; - static const int version_patch = 0; + static const int version_patch = 1; static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; static const char *compiler_name = CHAISCRIPT_COMPILER_NAME; diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index b27db07..8ea30ef 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -933,7 +933,17 @@ TEST_CASE("Map conversions") )"); CHECK(c == 42); +} + +TEST_CASE("Parse floats with non-posix locale") +{ + std::cout << "Current locale: " << std::setlocale(LC_ALL, "en_ZA.utf8") << '\n'; + chaiscript::ChaiScript chai; + const double parsed = chai.eval("print(1.3); 1.3"); + CHECK(parsed == 1.3); + const std::string str = chai.eval("to_string(1.3)"); + CHECK(str == "1.3"); } From 2a8c248167817428bfbf0f06c723d908117f0e0d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 15:18:12 -0700 Subject: [PATCH 07/33] Implement locale dependent float parser closes #250 --- include/chaiscript/chaiscript_defines.hpp | 67 +++++++++++++++++++ .../chaiscript/language/chaiscript_parser.hpp | 6 +- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index cf2a5a6..98fbf4a 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -93,6 +93,8 @@ #endif #include +#include +#include namespace chaiscript { static const int version_major = 5; @@ -119,6 +121,71 @@ namespace chaiscript { return iter; } + + template + auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type + { + T t = 0; + for (char c = *t_str; (c = *t_str); ++t_str) { + if (c < '0' || c > '9') { + return t; + } + t *= 10; + t += c - '0'; + } + return t; + } + + + template + auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type + { + T t = 0; + T base = 0; + T decimal_place = 0; + bool exponent = false; + bool neg_exponent = false; + + const auto final_value = [](const T val, const T baseval, const bool hasexp, const bool negexp) -> T { + if (!hasexp) { + return val; + } else { + return baseval * std::pow(T(10), val*T(negexp?-1:1)); + } + }; + + for(char c = *t_str; (c = *t_str); ++t_str) { + if (c == '.') { + decimal_place = 10; + } else if (c == 'e' || c == 'E') { + exponent = true; + decimal_place = 0; + base = t; + t = 0; + } else if (c == '-' && exponent) { + neg_exponent = true; + } else if (c == '+' && exponent) { + neg_exponent = false; + } else if (c < '0' || c > '9') { + return final_value(t, base, exponent, neg_exponent); + } else if (decimal_place == 0) { + t *= T(10); + t += T(c - '0'); + } else { + t += (T(c - '0') / (T(decimal_place))); + decimal_place *= 10; + } + } + + return final_value(t, base, exponent, neg_exponent); + } + + template + T parse_num(const std::string &t_str) + { + return parse_num(t_str.c_str()); + } + } #endif diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 684b766..8fc9827 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -621,11 +621,11 @@ namespace chaiscript if (float_) { - return const_var(std::stof(t_val.substr(0,i))); + return const_var(parse_num(t_val.substr(0,i))); } else if (long_) { - return const_var(std::stold(t_val.substr(0,i))); + return const_var(parse_num(t_val.substr(0,i))); } else { - return const_var(std::stod(t_val.substr(0,i))); + return const_var(parse_num(t_val.substr(0,i))); } } From b663654a6dfce5454246fbb4a489c1c569947a53 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 15:49:31 -0700 Subject: [PATCH 08/33] Add missing header for locale --- unittests/compiled_tests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 8ea30ef..0150210 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -28,6 +28,8 @@ #define CATCH_CONFIG_MAIN +#include + #include "catch.hpp" // lambda_tests From 0eee23109e7d47dc5185e1578b167a0fa79cea66 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 16:05:08 -0700 Subject: [PATCH 09/33] Upgrade catch to new version --- include/chaiscript/chaiscript_defines.hpp | 2 +- unittests/catch.hpp | 3223 ++++++++++++++------- unittests/compiled_tests.cpp | 15 +- 3 files changed, 2108 insertions(+), 1132 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 98fbf4a..1036a13 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -168,7 +168,7 @@ namespace chaiscript { neg_exponent = false; } else if (c < '0' || c > '9') { return final_value(t, base, exponent, neg_exponent); - } else if (decimal_place == 0) { + } else if (decimal_place < T(10)) { t *= T(10); t += T(c - '0'); } else { diff --git a/unittests/catch.hpp b/unittests/catch.hpp index 5b616a2..5b9bfc2 100644 --- a/unittests/catch.hpp +++ b/unittests/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.1 build 1 (master branch) - * Generated: 2015-03-27 18:00:16.346230 + * Catch v1.3.5 + * Generated: 2016-02-29 08:16:42.342094 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -13,9 +13,13 @@ #define TWOBLUECUBES_CATCH_HPP_INCLUDED -// #included from: internal/catch_suppress_warnings.h +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif -#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED +// #included from: internal/catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro @@ -30,6 +34,8 @@ # pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" @@ -37,7 +43,6 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif - #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL #endif @@ -69,70 +74,86 @@ // #included from: catch_compiler_capabilities.h #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED -// Much of the following code is based on Boost (1.53) +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#if defined(__cplusplus) && __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +#endif #ifdef __clang__ # if __has_feature(cxx_nullptr) -# define CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif # if __has_feature(cxx_noexcept) -# define CATCH_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // Borland #ifdef __BORLANDC__ -#if (__BORLANDC__ > 0x582 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - #endif // __BORLANDC__ //////////////////////////////////////////////////////////////////////////////// // EDG #ifdef __EDG_VERSION__ -#if (__EDG_VERSION__ > 238 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - #endif // __EDG_VERSION__ //////////////////////////////////////////////////////////////////////////////// // Digital Mars #ifdef __DMC__ -#if (__DMC__ > 0x840 ) -//#define CATCH_CONFIG_SFINAE // Not confirmed -#endif - #endif // __DMC__ //////////////////////////////////////////////////////////////////////////////// // GCC #ifdef __GNUC__ -#if __GNUC__ < 3 +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif -#if (__GNUC_MINOR__ >= 96 ) -//#define CATCH_CONFIG_SFINAE -#endif +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "gcc diagnostic ignored \"-Wparentheses\"" ) +# endif -#elif __GNUC__ >= 3 - -// #define CATCH_CONFIG_SFINAE // Taking this out completely for now - -#endif // __GNUC__ < 3 - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) - -#define CATCH_CONFIG_CPP11_NULLPTR -#endif +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below #endif // __GNUC__ @@ -141,36 +162,103 @@ #ifdef _MSC_VER #if (_MSC_VER >= 1600) -#define CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif -#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) -//#define CATCH_CONFIG_SFINAE // Not confirmed +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #endif #endif // _MSC_VER +//////////////////////////////////////////////////////////////////////////////// + // Use variadic macros if the compiler supports them #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ ( defined __GNUC__ && __GNUC__ >= 3 ) || \ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) -#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS -#define CATCH_CONFIG_VARIADIC_MACROS -#endif +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS #endif //////////////////////////////////////////////////////////////////////////////// // C++ language feature support -// detect language version: -#if (__cplusplus == 201103L) -# define CATCH_CPP11 -# define CATCH_CPP11_OR_GREATER -#elif (__cplusplus >= 201103L) -# define CATCH_CPP11_OR_GREATER +// catch all support for C++11 +#if defined(CATCH_CPP11_OR_GREATER) + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS #endif // noexcept support: @@ -182,10 +270,38 @@ # define CATCH_NOEXCEPT_IS(x) #endif +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + namespace Catch { + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + class NonCopyable { -#ifdef CATCH_CPP11_OR_GREATER +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; @@ -248,7 +364,7 @@ namespace Catch { SourceLineInfo(); SourceLineInfo( char const* _file, std::size_t _line ); SourceLineInfo( SourceLineInfo const& other ); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; @@ -270,6 +386,9 @@ namespace Catch { void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as @@ -355,7 +474,7 @@ namespace Catch { template class Ptr { public: - Ptr() : m_p( NULL ){} + Ptr() : m_p( CATCH_NULL ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); @@ -371,7 +490,7 @@ namespace Catch { void reset() { if( m_p ) m_p->release(); - m_p = NULL; + m_p = CATCH_NULL; } Ptr& operator = ( T* p ){ Ptr temp( p ); @@ -384,12 +503,11 @@ namespace Catch { return *this; } void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() { return m_p; } - const T* get() const{ return m_p; } + T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } - bool operator !() const { return m_p == NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } private: T* m_p; @@ -486,9 +604,13 @@ namespace Catch { struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector const& getAllTests() const = 0; - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const = 0; - + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + } namespace Catch { @@ -521,27 +643,32 @@ struct NameAndDesc { const char* description; }; +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + struct AutoReg { - AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); template - AutoReg( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - registerTestCase( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - void registerTestCase( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } ~AutoReg(); @@ -550,6 +677,11 @@ private: void operator= ( AutoReg const& ); }; +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS @@ -573,6 +705,10 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ @@ -594,6 +730,9 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); #endif // #included from: internal/catch_capture.hpp @@ -637,11 +776,11 @@ namespace Catch { // ResultDisposition::Flags enum struct ResultDisposition { enum Flags { - Normal = 0x00, + Normal = 0x01, - ContinueOnFailure = 0x01, // Failures fail test, but execution continues - FalseTest = 0x02, // Prefix expression with ! - SuppressFail = 0x04 // Failures are reported but do not fail the test + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test }; }; inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { @@ -689,7 +828,7 @@ namespace Catch { AssertionResult(); AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); ~AssertionResult(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionResult( AssertionResult const& ) = default; AssertionResult( AssertionResult && ) = default; AssertionResult& operator = ( AssertionResult const& ) = default; @@ -716,6 +855,323 @@ namespace Catch { } // end namespace Catch +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + namespace Catch { struct TestFailureException{}; @@ -742,11 +1198,12 @@ namespace Catch { ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ); + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); template - ExpressionLhs operator->* ( T const& operand ); - ExpressionLhs operator->* ( bool value ); + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); template ResultBuilder& operator << ( T const& value ) { @@ -771,6 +1228,9 @@ namespace Catch { void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; bool allowThrows() const; @@ -841,37 +1301,37 @@ namespace Internal { template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs) { - return opCast( lhs ) == opCast( rhs ); + return bool( opCast( lhs ) == opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) != opCast( rhs ); + return bool( opCast( lhs ) != opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) < opCast( rhs ); + return bool( opCast( lhs ) < opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) > opCast( rhs ); + return bool( opCast( lhs ) > opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) >= opCast( rhs ); + return bool( opCast( lhs ) >= opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) <= opCast( rhs ); + return bool( opCast( lhs ) <= opCast( rhs ) ); } }; @@ -949,13 +1409,51 @@ namespace Internal { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( NULL, rhs ); + return Evaluator::evaluate( nullptr, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, NULL ); + return Evaluator::evaluate( lhs, nullptr ); } #endif // CATCH_CONFIG_CPP11_NULLPTR @@ -969,40 +1467,6 @@ namespace Internal { // #included from: catch_tostring.h #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED -// #included from: catch_sfinae.hpp -#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED - -// Try to detect if the current compiler supports SFINAE - -namespace Catch { - - struct TrueType { - static const bool value = true; - typedef void Enable; - char sizer[1]; - }; - struct FalseType { - static const bool value = false; - typedef void Disable; - char sizer[2]; - }; - -#ifdef CATCH_CONFIG_SFINAE - - template struct NotABooleanExpression; - - template struct If : NotABooleanExpression {}; - template<> struct If : TrueType {}; - template<> struct If : FalseType {}; - - template struct SizedIf; - template<> struct SizedIf : TrueType {}; - template<> struct SizedIf : FalseType {}; - -#endif // CATCH_CONFIG_SFINAE - -} // end namespace Catch - #include #include #include @@ -1055,8 +1519,11 @@ inline id performOptionalSelector( id obj, SEL sel ) { #endif -#ifdef CATCH_CPP11_OR_GREATER +#ifdef CATCH_CONFIG_CPP11_TUPLE #include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM #include #endif @@ -1084,6 +1551,11 @@ std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); #endif @@ -1096,34 +1568,15 @@ std::string toString( std::nullptr_t ); namespace Detail { - extern std::string unprintableString; - -// SFINAE is currently disabled by default for all compilers. -// If the non SFINAE version of IsStreamInsertable is ambiguous for you -// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE -#ifdef CATCH_CONFIG_SFINAE - - template - class IsStreamInsertableHelper { - template struct TrueIfSizeable : TrueType {}; - - template - static TrueIfSizeable dummy(T2*); - static FalseType dummy(...); - - public: - typedef SizedIf type; - }; - - template - struct IsStreamInsertable : IsStreamInsertableHelper::type {}; - -#else + extern const std::string unprintableString; struct BorgType { template BorgType( T const& ); }; + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + TrueType& testStreamable( std::ostream& ); FalseType testStreamable( FalseType ); @@ -1136,9 +1589,7 @@ namespace Detail { enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; }; -#endif - -#if defined(CATCH_CPP11_OR_GREATER) +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) template::value > @@ -1160,7 +1611,7 @@ namespace Detail { #endif template struct StringMakerBase { -#if defined(CATCH_CPP11_OR_GREATER) +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) template static std::string convert( T const& v ) { @@ -1200,7 +1651,7 @@ struct StringMaker { template static std::string convert( U* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -1210,7 +1661,7 @@ template struct StringMaker { static std::string convert( R C::* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -1233,7 +1684,7 @@ std::string toString( std::vector const& v ) { return Detail::rangeToString( v.begin(), v.end() ); } -#ifdef CATCH_CPP11_OR_GREATER +#ifdef CATCH_CONFIG_CPP11_TUPLE // toString for tuples namespace TupleDetail { @@ -1273,7 +1724,7 @@ struct StringMaker> { return os.str(); } }; -#endif +#endif // CATCH_CONFIG_CPP11_TUPLE namespace Detail { template @@ -1318,13 +1769,13 @@ namespace Catch { template class ExpressionLhs { ExpressionLhs& operator = ( ExpressionLhs const& ); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS ExpressionLhs& operator = ( ExpressionLhs && ) = delete; # endif public: ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS ExpressionLhs( ExpressionLhs const& ) = default; ExpressionLhs( ExpressionLhs && ) = default; # endif @@ -1405,11 +1856,11 @@ private: namespace Catch { template - inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { return ExpressionLhs( *this, operand ); } - inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { return ExpressionLhs( *this, value ); } @@ -1482,6 +1933,7 @@ namespace Catch { class AssertionResult; struct AssertionInfo; struct SectionInfo; + struct SectionEndInfo; struct MessageInfo; class ScopedMessageBuilder; struct Counts; @@ -1493,7 +1945,8 @@ namespace Catch { virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; @@ -1581,13 +2034,14 @@ namespace Catch { do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ - ( __catchResult->*expr ).endExpression(); \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + ( __catchResult <= expr ).endExpression(); \ } \ catch( ... ) { \ __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + } while( Catch::isTrue( false && static_cast(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ @@ -1614,16 +2068,16 @@ namespace Catch { } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ try { \ expr; \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + __catchResult.captureExpectedException( matcher ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ @@ -1676,14 +2130,14 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ try { \ - std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + std::string matcherAsString = (matcher).toString(); \ __catchResult \ .setLhs( Catch::toString( arg ) ) \ .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ .setOp( "matches" ) \ - .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + .setResultType( (matcher).match( arg ) ); \ __catchResult.captureExpression(); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ @@ -1697,21 +2151,6 @@ namespace Catch { // #included from: catch_section_info.h #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - -} // end namespace Catch - // #included from: catch_totals.hpp #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED @@ -1782,6 +2221,31 @@ namespace Catch { }; } +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + // #included from: catch_timer.h #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED @@ -2022,6 +2486,8 @@ using namespace Generators; #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include +#include + // #included from: catch_interfaces_registry_hub.h #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED @@ -2046,7 +2512,8 @@ namespace Catch { struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; }; @@ -2058,14 +2525,16 @@ namespace Catch { } - namespace Catch { typedef std::string(*exceptionTranslateFunction)(); + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + struct IExceptionTranslator { virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { @@ -2083,9 +2552,12 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate() const { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { - throw; + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); @@ -2192,231 +2664,6 @@ inline std::string toString( Detail::Approx const& value ) { } // end namespace Catch -// #included from: internal/catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct Equals : MatcherImpl { - Equals( std::string const& str ) : m_str( str ){} - Equals( Equals const& other ) : m_str( other.m_str ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_str == expr; - } - virtual std::string toString() const { - return "equals: \"" + m_str + "\""; - } - - std::string m_str; - }; - - struct Contains : MatcherImpl { - Contains( std::string const& substr ) : m_substr( substr ){} - Contains( Contains const& other ) : m_substr( other.m_substr ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr ) : m_substr( substr ){} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == 0; - } - virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr ) : m_substr( substr ){} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); - } - virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str ) { - return Impl::StdString::Equals( str ); - } - inline Impl::StdString::Equals Equals( const char* str ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); - } - inline Impl::StdString::Contains Contains( std::string const& substr ) { - return Impl::StdString::Contains( substr ); - } - inline Impl::StdString::Contains Contains( const char* substr ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - // #included from: internal/catch_interfaces_tag_alias_registry.h #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED @@ -2450,12 +2697,12 @@ namespace Catch { template class Option { public: - Option() : nullableValue( NULL ) {} + Option() : nullableValue( CATCH_NULL ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) {} ~Option() { @@ -2479,7 +2726,7 @@ namespace Catch { void reset() { if( nullableValue ) nullableValue->~T(); - nullableValue = NULL; + nullableValue = CATCH_NULL; } T& operator*() { return *nullableValue; } @@ -2491,10 +2738,10 @@ namespace Catch { return nullableValue ? *nullableValue : defaultValue; } - bool some() const { return nullableValue != NULL; } - bool none() const { return nullableValue == NULL; } + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } - bool operator !() const { return nullableValue == NULL; } + bool operator !() const { return nullableValue == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } @@ -2552,6 +2799,8 @@ namespace Catch { TestCaseInfo( TestCaseInfo const& other ); + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + bool isHidden() const; bool throws() const; bool okToFail() const; @@ -2664,7 +2913,7 @@ namespace Catch { inline size_t registerTestMethods() { size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); + int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); @@ -2806,7 +3055,7 @@ return @ desc; \ #pragma clang diagnostic ignored "-Wweak-vtables" #endif -// #included from: ../catch_runner.hpp +// #included from: ../catch_session.hpp #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED // #included from: internal/catch_commandline.hpp @@ -2831,6 +3080,67 @@ return @ desc; \ #pragma clang diagnostic ignored "-Wpadded" #endif +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + #include #include @@ -2842,50 +3152,18 @@ namespace Catch { virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { - if( startsWith( m_name, "*" ) ) { - m_name = m_name.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_name, "*" ) ) { - m_name = m_name.substr( 0, m_name.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_name == toLower( testCase.name ); - case WildcardAtStart: - return endsWith( toLower( testCase.name ), m_name ); - case WildcardAtEnd: - return startsWith( toLower( testCase.name ), m_name ); - case WildcardAtBothEnds: - return contains( toLower( testCase.name ), m_name ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif + return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: - std::string m_name; - WildcardPosition m_wildcard; + WildcardPattern m_wildcardPattern; }; + class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} @@ -2896,6 +3174,7 @@ namespace Catch { private: std::string m_tag; }; + class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} @@ -3067,6 +3346,11 @@ namespace Catch { InLexicographicalOrder, InRandomOrder }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; class TestSpec; @@ -3086,35 +3370,69 @@ namespace Catch { virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; - virtual bool forceColour() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; }; } // #included from: catch_stream.h #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED -#include +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif +#include namespace Catch { - class Stream { + class StreamBufBase : public std::streambuf { public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); - - std::streambuf* streamBuf; - - private: - bool isOwned; + virtual ~StreamBufBase() CATCH_NOEXCEPT; }; +} + +#include +#include +#include + +namespace Catch { std::ostream& cout(); std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; } #include @@ -3141,13 +3459,14 @@ namespace Catch { noThrow( false ), showHelp( false ), showInvisibles( false ), - forceColour( false ), + filenamesAsTags( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), warnings( WarnAbout::Nothing ), showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ) + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) {} bool listTests; @@ -3160,7 +3479,7 @@ namespace Catch { bool noThrow; bool showHelp; bool showInvisibles; - bool forceColour; + bool filenamesAsTags; int abortAfter; unsigned int rngSeed; @@ -3169,12 +3488,13 @@ namespace Catch { WarnAbout::What warnings; ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; - std::string reporterName; std::string outputFilename; std::string name; std::string processName; + std::vector reporterNames; std::vector testsOrTags; }; @@ -3186,12 +3506,11 @@ namespace Catch { public: Config() - : m_os( Catch::cout().rdbuf() ) {} Config( ConfigData const& data ) : m_data( data ), - m_os( Catch::cout().rdbuf() ) + m_stream( openStream() ) { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); @@ -3202,12 +3521,6 @@ namespace Catch { } virtual ~Config() { - m_os.rdbuf( Catch::cout().rdbuf() ); - m_stream.release(); - } - - void setFilename( std::string const& filename ) { - m_data.outputFilename = filename; } std::string const& getFilename() const { @@ -3223,18 +3536,7 @@ namespace Catch { bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() ); - } - - void useStream( std::string const& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - - std::string getReporterName() const { return m_data.reporterName; } + std::vector getReporterNames() const { return m_data.reporterNames; } int abortAfter() const { return m_data.abortAfter; } @@ -3245,20 +3547,32 @@ namespace Catch { // IConfig interface virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_os; } + virtual std::ostream& stream() const { return m_stream->stream(); } virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } virtual unsigned int rngSeed() const { return m_data.rngSeed; } - virtual bool forceColour() const { return m_data.forceColour; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } ConfigData m_data; - Stream m_stream; - mutable std::ostream m_os; + std::auto_ptr m_stream; TestSpec m_testSpec; }; @@ -3278,6 +3592,8 @@ namespace Catch { #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { // #included from: ../external/clara.h +// Version 0.0.1.1 + // Only use header guard if we are not using an outer namespace #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) @@ -3302,6 +3618,7 @@ namespace Catch { #include #include #include +#include // Use optional outer namespace #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE @@ -3436,12 +3753,158 @@ namespace Tbc { #endif // TBC_TEXT_FORMAT_H_INCLUDED // ----------- end of #include from tbc_text_format.h ----------- -// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h +// ........... back in clara.h #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + #include -#include #include #include @@ -3468,6 +3931,9 @@ namespace Clara { const unsigned int consoleWidth = 80; #endif + // Use this to try and stop compiler from warning about unreachable code + inline bool isTrue( bool value ) { return value; } + using namespace Tbc; inline bool startsWith( std::string const& str, std::string const& prefix ) { @@ -3508,16 +3974,17 @@ namespace Clara { } template inline void convertInto( bool, T& ) { - throw std::runtime_error( "Invalid conversion" ); + if( isTrue( true ) ) + throw std::runtime_error( "Invalid conversion" ); } template struct IArgFunction { virtual ~IArgFunction() {} -# ifdef CATCH_CPP11_OR_GREATER +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS IArgFunction() = default; IArgFunction( IArgFunction const& ) = default; -# endif +#endif virtual void set( ConfigT& config, std::string const& value ) const = 0; virtual void setFlag( ConfigT& config ) const = 0; virtual bool takesArg() const = 0; @@ -3527,11 +3994,11 @@ namespace Clara { template class BoundArgFunction { public: - BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction() : functionObj( CLARA_NULL ) {} BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; delete functionObj; functionObj = newFunctionObj; return *this; @@ -3547,7 +4014,7 @@ namespace Clara { bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { - return functionObj != NULL; + return functionObj != CLARA_NULL; } private: IArgFunction* functionObj; @@ -3655,7 +4122,7 @@ namespace Clara { std::string data; }; - void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + void parseIntoTokens( int argc, char const* const argv[], std::vector& tokens ) const { const std::string doubleDash = "--"; for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) parseIntoTokens( argv[i] , tokens); @@ -3765,12 +4232,7 @@ namespace Clara { } }; - // NOTE: std::auto_ptr is deprecated in c++11/c++0x -#if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr ArgAutoPtr; -#else - typedef std::auto_ptr ArgAutoPtr; -#endif + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; friend void addOptName( Arg& arg, std::string const& optName ) { @@ -3994,13 +4456,13 @@ namespace Clara { return oss.str(); } - ConfigT parse( int argc, char const * const * argv ) const { + ConfigT parse( int argc, char const* const argv[] ) const { ConfigT config; parseInto( argc, argv, config ); return config; } - std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::vector parseInto( int argc, char const* argv[], ConfigT& config ) const { std::string processName = argv[0]; std::size_t lastSlash = processName.find_last_of( "/\\" ); if( lastSlash != std::string::npos ) @@ -4143,6 +4605,7 @@ namespace Catch { config.abortAfter = x; } inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } inline void addWarning( ConfigData& config, std::string const& _warning ) { if( _warning == "NoAssertions" ) @@ -4181,6 +4644,21 @@ namespace Catch { ? ShowDurations::Always : ShowDurations::Never; } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { std::ifstream f( _filename.c_str() ); if( !f.is_open() ) @@ -4236,7 +4714,7 @@ namespace Catch { cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) .describe( "reporter to use (defaults to console)" ) - .bind( &ConfigData::reporterName, "name" ); + .bind( &addReporterName, "name" ); cli["-n"]["--name"] .describe( "suite name" ) @@ -4267,12 +4745,16 @@ namespace Catch { cli["-d"]["--durations"] .describe( "show test durations" ) - .bind( &setShowDurations, "yes/no" ); + .bind( &setShowDurations, "yes|no" ); cli["-f"]["--input-file"] .describe( "load test names to run from a file" ) .bind( &loadTestNamesFromFile, "filename" ); + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) @@ -4291,8 +4773,12 @@ namespace Catch { .bind( &setRngSeed, "'time'|number" ); cli["--force-colour"] - .describe( "force colourised output" ) - .bind( &ConfigData::forceColour ); + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); return cli; } @@ -4530,18 +5016,18 @@ namespace Catch { namespace Catch { struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) + explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } + Ptr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; - Ptr m_fullConfig; + Ptr m_fullConfig; }; struct ReporterPreferences { @@ -4605,7 +5091,7 @@ namespace Catch } virtual ~AssertionStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; @@ -4628,7 +5114,7 @@ namespace Catch missingAssertions( _missingAssertions ) {} virtual ~SectionStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SectionStats( SectionStats const& ) = default; SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; @@ -4655,7 +5141,7 @@ namespace Catch {} virtual ~TestCaseStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; @@ -4683,7 +5169,7 @@ namespace Catch {} virtual ~TestGroupStats(); -# ifdef CATCH_CPP11_OR_GREATER +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; @@ -4705,7 +5191,7 @@ namespace Catch {} virtual ~TestRunStats(); -# ifndef CATCH_CPP11_OR_GREATER +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS TestRunStats( TestRunStats const& _other ) : runInfo( _other.runInfo ), totals( _other.totals ), @@ -4743,6 +5229,7 @@ namespace Catch // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; @@ -4751,20 +5238,24 @@ namespace Catch virtual void skipTest( TestCaseInfo const& testInfo ) = 0; }; - struct IReporterFactory { + struct IReporterFactory : IShared { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; struct IReporterRegistry { - typedef std::map FactoryMap; + typedef std::map > FactoryMap; + typedef std::vector > Listeners; virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; }; + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + } #include @@ -4787,8 +5278,7 @@ namespace Catch { nameAttr.setInitialIndent( 2 ).setIndent( 4 ); tagsAttr.setIndent( 6 ); - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4816,8 +5306,7 @@ namespace Catch { if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4857,8 +5346,7 @@ namespace Catch { std::map tagCounts; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4929,7 +5417,7 @@ namespace Catch { } // end namespace Catch -// #included from: internal/catch_runner_impl.hpp +// #included from: internal/catch_run_context.hpp #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED // #included from: catch_test_case_tracker.hpp @@ -4938,132 +5426,300 @@ namespace Catch { #include #include #include +#include namespace Catch { -namespace SectionTracking { +namespace TestCaseTracking { - class TrackedSection { + struct ITracker : SharedImpl<> { + virtual ~ITracker(); - typedef std::map TrackedSections; + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { - public: enum RunState { NotStarted, Executing, - ExecutingChildren, - Completed + CompletedCycle }; - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) {} - RunState runState() const { return m_runState; } + ITracker& startRun(); - TrackedSection* findChild( std::string const& childName ) { - TrackedSections::iterator it = m_children.find( childName ); - return it != m_children.end() - ? &it->second - : NULL; + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; } - TrackedSection* acquireChild( std::string const& childName ) { - if( TrackedSection* child = findChild( childName ) ) - return child; - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - return findChild( childName ); + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; } - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; + void completeCycle() { + m_runState = CompletedCycle; } - void leave() { - for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if( it->second.runState() != Completed ) { - m_runState = ExecutingChildren; - return; - } - m_runState = Completed; + + bool completedCycle() const { + return m_runState == CompletedCycle; } - TrackedSection* getParent() { - return m_parent; + ITracker& currentTracker() { + return *m_currentTracker; } - bool hasChildren() const { + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { return !m_children.empty(); } - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } }; - class TestCaseTracker { + class SectionTracker : public TrackerBase { public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) {} + virtual ~SectionTracker(); - bool enterSection( std::string const& name ) { - TrackedSection* child = m_currentSection->acquireChild( name ); - if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) - return false; + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; - m_currentSection = child; - m_currentSection->enter(); - return true; - } - void leaveSection() { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); - m_completedASectionThisRun = true; - } - - bool currentSectionHasChildren() const { - return m_currentSection->hasChildren(); - } - bool isCompleted() const { - return m_testCase.runState() == TrackedSection::Completed; - } - - class Guard { - public: - Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { - m_tracker.enterTestCase(); + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); + assert( section ); } - ~Guard() { - m_tracker.leaveTestCase(); + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; + if( !ctx.completedCycle() && !section->isComplete() ) { - private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); + section->open(); + } + return *section; } - void leaveTestCase() { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; }; -} // namespace SectionTracking + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); -using SectionTracking::TestCaseTracker; + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; } // namespace Catch @@ -5179,15 +5835,12 @@ namespace Catch { public: - explicit RunContext( Ptr const& config, Ptr const& reporter ) - : m_runInfo( config->name() ), + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), - m_activeTestCase( NULL ), - m_config( config ), - m_reporter( reporter ), - m_prevRunner( m_context.getRunner() ), - m_prevResultCapture( m_context.getResultCapture() ), - m_prevConfig( m_context.getConfig() ) + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -5197,10 +5850,6 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { @@ -5221,14 +5870,17 @@ namespace Catch { m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; - m_testCaseTracker = TestCaseTracker( testInfo.name ); do { + m_trackerContext.startRun(); do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); runCurrentTest( redirectedCout, redirectedCerr ); } - while( !m_testCaseTracker->isCompleted() && !aborting() ); + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } + // !TBD: deprecated - this will be replaced by indexed trackers while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); @@ -5239,8 +5891,8 @@ namespace Catch { redirectedCerr, aborting() ) ); - m_activeTestCase = NULL; - m_testCaseTracker.reset(); + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; return deltaTotals; } @@ -5275,8 +5927,10 @@ namespace Catch { std::ostringstream oss; oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - if( !m_testCaseTracker->enterSection( oss.str() ) ) + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) return false; + m_activeSections.push_back( §ionTracker ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; @@ -5287,30 +5941,40 @@ namespace Catch { return true; } bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) return false; m_totals.assertions.failed++; assertions.failed++; return true; } - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { - if( std::uncaught_exception() ) { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; - } - - Counts assertions = m_totals.assertions - prevAssertions; + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); - m_testCaseTracker->leaveSection(); + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } @@ -5376,7 +6040,8 @@ namespace Catch { double duration = 0; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); + + seedRng( *m_config ); Timer timer; timer.start(); @@ -5396,6 +6061,7 @@ namespace Catch { catch(...) { makeUnexpectedResultBuilder().useActiveException(); } + m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); @@ -5430,39 +6096,29 @@ namespace Catch { void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it ) - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + sectionEnded( *it ); m_unfinishedSections.clear(); } - struct UnfinishedSections { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) - : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; - }; - TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; - Option m_testCaseTracker; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; AssertionResult m_lastResult; Ptr m_config; Totals m_totals; Ptr m_reporter; std::vector m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; }; IResultCapture& getResultCapture() { @@ -5483,18 +6139,19 @@ namespace Catch { struct Version { Version( unsigned int _majorVersion, unsigned int _minorVersion, - unsigned int _buildNumber, - char const* const _branchName ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - buildNumber( _buildNumber ), - branchName( _branchName ) - {} + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); unsigned int const majorVersion; unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; unsigned int const buildNumber; - char const* const branchName; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); private: void operator=( Version const& ); @@ -5509,89 +6166,87 @@ namespace Catch { namespace Catch { - class Runner { + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } - public: - Runner( Ptr const& config ) - : m_config( config ) - { - openStream(); - makeReporter(); + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); } - Totals runTests() { + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } - RunContext context( m_config.get(), m_reporter ); + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; - Totals totals; + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); - context.testGroupStarting( "all tests", 1, 1 ); // deprecated? + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); - TestSpec testSpec = m_config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); - - int testsRunForGroup = 0; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) { - testsRunForGroup++; - if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); - } - } - std::vector skippedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true ); - - for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); - it != itEnd; - ++it ) - m_reporter->skipTest( *it ); - - context.testGroupEnded( "all tests", totals, 1, 1 ); - return totals; + tags.insert( "#" + filename ); + setTags( test, tags ); } - - private: - void openStream() { - // Open output file, if specified - if( !m_config->getFilename().empty() ) { - m_ofs.open( m_config->getFilename().c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - m_config->setStreamBuf( m_ofs.rdbuf() ); - } - } - void makeReporter() { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if( !m_reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - } - - private: - Ptr m_config; - std::ofstream m_ofs; - Ptr m_reporter; - std::set m_testsAlreadyRun; - }; + } class Session : NonCopyable { static bool alreadyInstantiated; @@ -5614,18 +6269,13 @@ namespace Catch { } void showHelp( std::string const& processName ) { - Catch::cout() << "\nCatch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " build " - << libraryVersion.buildNumber; - if( libraryVersion.branchName != std::string( "master" ) ) - Catch::cout() << " (" << libraryVersion.branchName << " branch)"; - Catch::cout() << "\n"; + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; m_cli.usage( Catch::cout(), processName ); Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); @@ -5636,9 +6286,10 @@ namespace Catch { catch( std::exception& ex ) { { Colour colourGuard( Colour::Red ); - Catch::cerr() << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; } m_cli.usage( Catch::cout(), m_configData.processName ); return (std::numeric_limits::max)(); @@ -5651,13 +6302,16 @@ namespace Catch { m_config.reset(); } - int run( int argc, char* const argv[] ) { + int run( int argc, char const* argv[] ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); return returnCode; } + int run( int argc, char* argv[] ) { + return run( argc, const_cast( argv ) ); + } int run() { if( m_configData.showHelp ) @@ -5667,15 +6321,16 @@ namespace Catch { { config(); // Force config to be constructed - std::srand( m_configData.rngSeed ); + seedRng( *m_config ); - Runner runner( m_config ); + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); - return static_cast( runner.runTests().assertions.failed ); + return static_cast( runTests( m_config ).assertions.failed ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; @@ -5697,7 +6352,6 @@ namespace Catch { m_config = new Config( m_configData ); return *m_config; } - private: Clara::CommandLine m_cli; std::vector m_unusedTokens; @@ -5723,16 +6377,76 @@ namespace Catch { namespace Catch { - class TestRegistry : public ITestCaseRegistry { - struct LexSort { - bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { public: - TestRegistry() : m_unnamedCount( 0 ) {} + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} virtual ~TestRegistry(); virtual void registerTest( TestCase const& testCase ) { @@ -5742,69 +6456,29 @@ namespace Catch { oss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( oss.str() ) ); } - - if( m_functions.find( testCase ) == m_functions.end() ) { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if( !testCase.isHidden() ) - m_nonHiddenFunctions.push_back( testCase ); - } - else { - TestCase const& prev = *m_functions.find( testCase ); - { - Colour colourGuard( Colour::Red ); - Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - } - exit(1); - } + m_functions.push_back( testCase ); } virtual std::vector const& getAllTests() const { - return m_functionsInOrder; + return m_functions; } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); - virtual std::vector const& getAllNonHiddenTests() const { - return m_nonHiddenFunctions; - } - - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const { - - for( std::vector::const_iterator it = m_functionsInOrder.begin(), - itEnd = m_functionsInOrder.end(); - it != itEnd; - ++it ) { - bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ); - if( includeTest != negated ) - matchingTestCases.push_back( *it ); + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); } - sortTests( config, matchingTestCases ); + return m_sortedFunctions; } private: - - static void sortTests( IConfig const& config, std::vector& matchingTestCases ) { - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() ); - break; - case RunTests::InRandomOrder: - { - RandomNumberGenerator rng; - std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - } - std::set m_functions; - std::vector m_functionsInOrder; - std::vector m_nonHiddenFunctions; + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; /////////////////////////////////////////////////////////////////////////// @@ -5837,29 +6511,38 @@ namespace Catch { return className; } - /////////////////////////////////////////////////////////////////////////// + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); } - AutoReg::~AutoReg() {} + /////////////////////////////////////////////////////////////////////////// - void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); } + AutoReg::~AutoReg() {} + } // end namespace Catch // #included from: catch_reporter_registry.hpp @@ -5873,27 +6556,32 @@ namespace Catch { public: - virtual ~ReporterRegistry() { - deleteAllValues( m_factories ); - } + virtual ~ReporterRegistry() CATCH_OVERRIDE {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) - return NULL; + return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } - void registerReporter( std::string const& name, IReporterFactory* factory ) { + void registerReporter( std::string const& name, Ptr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } - FactoryMap const& getFactories() const { + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { return m_factories; } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } private: FactoryMap m_factories; + Listeners m_listeners; }; } @@ -5921,13 +6609,13 @@ namespace Catch { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { - throw; + return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else - throw; + return tryTranslators(); #endif } catch( TestFailureException& ) { @@ -5943,20 +6631,15 @@ namespace Catch { return msg; } catch(...) { - return tryTranslators( m_translators.begin() ); + return "Unknown exception"; } } - std::string tryTranslators( std::vector::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: @@ -5976,24 +6659,27 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const { + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const { + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerTest( TestCase const& testInfo ) { + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) { + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } @@ -6005,7 +6691,7 @@ namespace Catch { // Single, global, instance inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = NULL; + static RegistryHub* theRegistryHub = CATCH_NULL; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; @@ -6020,7 +6706,7 @@ namespace Catch { } void cleanUp() { delete getTheRegistryHub(); - getTheRegistryHub() = NULL; + getTheRegistryHub() = CATCH_NULL; cleanUpContext(); } std::string translateActiveException() { @@ -6056,19 +6742,6 @@ namespace Catch { // #included from: catch_stream.hpp #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - #include #include #include @@ -6113,6 +6786,19 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + struct OutputDebugWriter { void operator()( std::string const&str ) { @@ -6120,23 +6806,26 @@ namespace Catch { } }; - Stream::Stream() - : streamBuf( NULL ), isOwned( false ) + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) {} - Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) - {} - - void Stream::release() { - if( isOwned ) { - delete streamBuf; - streamBuf = NULL; - isOwned = false; - } + std::ostream& DebugOutStream::stream() const { + return m_os; } -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions std::ostream& cout() { return std::cout; } @@ -6150,7 +6839,7 @@ namespace Catch { class Context : public IMutableContext { - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} Context( Context const& ); void operator=( Context const& ); @@ -6196,7 +6885,7 @@ namespace Catch { m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second - : NULL; + : CATCH_NULL; } IGeneratorsForTest& getGeneratorsForCurrentTest() { @@ -6217,7 +6906,7 @@ namespace Catch { }; namespace { - Context* currentContext = NULL; + Context* currentContext = CATCH_NULL; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) @@ -6228,17 +6917,9 @@ namespace Catch { return getCurrentMutableContext(); } - Stream createStream( std::string const& streamName ) { - if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false ); - if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false ); - if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); - - throw std::domain_error( "Unknown stream: " + streamName ); - } - void cleanUpContext() { delete currentContext; - currentContext = NULL; + currentContext = CATCH_NULL; } } @@ -6294,12 +6975,13 @@ namespace { { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Red: return setTextAttribute( FOREGROUND_RED ); case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); @@ -6319,15 +7001,27 @@ namespace { private: void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); } HANDLE stdoutHandle; - WORD originalAttributes; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; }; IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; - return &s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); } } // end anon namespace @@ -6378,7 +7072,14 @@ namespace { IColourImpl* platformColourInstance() { Ptr config = getCurrentContext().getConfig(); - return (config && config->forceColour()) || isatty(STDOUT_FILENO) + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes ? PosixColourImpl::instance() : NoColourImpl::instance(); } @@ -6403,9 +7104,7 @@ namespace Catch { Colour::~Colour(){ if( !m_moved ) use( None ); } void Colour::use( Code _colourCode ) { - static IColourImpl* impl = isDebuggerActive() - ? NoColourImpl::instance() - : platformColourInstance(); + static IColourImpl* impl = platformColourInstance(); impl->use( _colourCode ); } @@ -6648,6 +7347,21 @@ namespace Catch { return TestCase( _testCase, info ); } + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, @@ -6656,18 +7370,10 @@ namespace Catch { : name( _name ), className( _className ), description( _description ), - tags( _tags ), lineInfo( _lineInfo ), properties( None ) { - std::ostringstream oss; - for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { - oss << "[" << *it << "]"; - std::string lcaseTag = toLower( *it ); - properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); - lcaseTags.insert( lcaseTag ); - } - tagsAsString = oss.str(); + setTags( *this, _tags ); } TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) @@ -6750,8 +7456,33 @@ namespace Catch { namespace Catch { - // These numbers are maintained by a script - Version libraryVersion( 1, 1, 1, "master" ); + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 3, 5, "", 0 ); + } // #included from: catch_message.hpp @@ -6943,7 +7674,7 @@ namespace Catch { #else uint64_t getCurrentTicks() { timeval t; - gettimeofday(&t,NULL); + gettimeofday(&t,CATCH_NULL); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif @@ -7042,6 +7773,14 @@ namespace Catch { return line < other.line || ( line == other.line && file < other.file ); } + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << "(" << info.line << ")"; @@ -7081,8 +7820,13 @@ namespace Catch { } Section::~Section() { - if( m_sectionIncluded ) - getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } } // This indicates whether the section should be executed or not @@ -7134,7 +7878,7 @@ namespace Catch { // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } @@ -7188,9 +7932,11 @@ namespace Catch { namespace Detail { - std::string unprintableString = "{?}"; + const std::string unprintableString = "{?}"; namespace { + const int hexThreshold = 255; + struct Endianness { enum Arch { Big, Little }; @@ -7271,19 +8017,17 @@ std::string toString( wchar_t* const value ) std::string toString( int value ) { std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; return oss.str(); } std::string toString( unsigned long value ) { std::ostringstream oss; - if( value > 8192 ) - oss << "0x" << std::hex << value; - else - oss << value; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; return oss.str(); } @@ -7332,6 +8076,23 @@ std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; @@ -7361,11 +8122,17 @@ std::string toString( std::nullptr_t ) { namespace Catch { + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), m_shouldDebugBreak( false ), m_shouldThrow( false ) {} @@ -7406,15 +8173,41 @@ namespace Catch { setResultType( resultType ); captureExpression(); } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } void ResultBuilder::captureExpression() { AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { getResultCapture().assertionEnded( result ); if( !result.isOk() ) { if( getCurrentContext().getConfig()->shouldDebugBreak() ) m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) m_shouldThrow = true; } } @@ -7561,6 +8354,137 @@ namespace Catch { } // end namespace Catch +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + // #included from: ../reporters/catch_reporter_xml.hpp #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED @@ -7576,47 +8500,53 @@ namespace Catch { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } - virtual ~StreamingReporterBase(); + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void noMatchingTestCases( std::string const& ) {} + virtual ~StreamingReporterBase() CATCH_OVERRIDE; - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { currentTestRunInfo = _testRunInfo; } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { currentGroupInfo = _groupInfo; } - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { currentTestCaseInfo = _testInfo; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_sectionStack.push_back( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { currentGroupInfo.reset(); } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } - virtual void skipTest( TestCaseInfo const& ) { + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } - Ptr m_config; + Ptr m_config; std::ostream& stream; LazyStat currentTestRunInfo; @@ -7624,6 +8554,7 @@ namespace Catch { LazyStat currentTestCaseInfo; std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; }; struct CumulativeReporterBase : SharedImpl { @@ -7674,15 +8605,21 @@ namespace Catch { CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } ~CumulativeReporterBase(); - virtual void testRunStarting( TestRunInfo const& ) {} - virtual void testGroupStarting( GroupInfo const& ) {} + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void testCaseStarting( TestCaseInfo const& ) {} + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { @@ -7707,7 +8644,7 @@ namespace Catch { m_deepestSection = node; } - virtual void assertionStarting( AssertionInfo const& ) {} + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& assertionStats ) { assert( !m_sectionStack.empty() ); @@ -7715,13 +8652,13 @@ namespace Catch { sectionNode.assertions.push_back( assertionStats ); return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); @@ -7732,12 +8669,12 @@ namespace Catch { m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); @@ -7745,9 +8682,9 @@ namespace Catch { } virtual void testRunEndedCumulative() = 0; - virtual void skipTest( TestCaseInfo const& ) {} + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - Ptr m_config; + Ptr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; @@ -7759,6 +8696,7 @@ namespace Catch { Ptr m_rootSection; Ptr m_deepestSection; std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; }; @@ -7772,6 +8710,17 @@ namespace Catch { return line; } + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + } // end namespace Catch // #included from: ../internal/catch_reporter_registrars.hpp @@ -7802,7 +8751,7 @@ namespace Catch { template class ReporterRegistrar { - class ReporterFactory : public IReporterFactory { + class ReporterFactory : public SharedImpl { // *** Please Note ***: // - If you end up here looking at a compiler error because it's trying to register @@ -7830,22 +8779,102 @@ namespace Catch { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + // #included from: ../internal/catch_xmlwriter.hpp #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #include #include #include +#include namespace Catch { + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + class XmlWriter { public: @@ -7857,7 +8886,7 @@ namespace Catch { ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ - other.m_writer = NULL; + other.m_writer = CATCH_NULL; } ~ScopedElement() { @@ -7897,27 +8926,6 @@ namespace Catch { endElement(); } -//# ifndef CATCH_CPP11_OR_GREATER -// XmlWriter& operator = ( XmlWriter const& other ) { -// XmlWriter temp( other ); -// swap( temp ); -// return *this; -// } -//# else -// XmlWriter( XmlWriter const& ) = default; -// XmlWriter( XmlWriter && ) = default; -// XmlWriter& operator = ( XmlWriter const& ) = default; -// XmlWriter& operator = ( XmlWriter && ) = default; -//# endif -// -// void swap( XmlWriter& other ) { -// std::swap( m_tagIsOpen, other.m_tagIsOpen ); -// std::swap( m_needsNewline, other.m_needsNewline ); -// std::swap( m_tags, other.m_tags ); -// std::swap( m_indent, other.m_indent ); -// std::swap( m_os, other.m_os ); -// } - XmlWriter& startElement( std::string const& name ) { ensureTagClosed(); newlineIfNecessary(); @@ -7949,11 +8957,8 @@ namespace Catch { } XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; return *this; } @@ -7964,9 +8969,9 @@ namespace Catch { template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - if( !name.empty() ) - stream() << " " << name << "=\"" << attribute << "\""; - return *this; + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { @@ -7975,7 +8980,7 @@ namespace Catch { ensureTagClosed(); if( tagWasOpen && indent ) stream() << m_indent; - writeEncodedText( text ); + stream() << XmlEncode( text ); m_needsNewline = true; } return *this; @@ -8020,30 +9025,6 @@ namespace Catch { } } - void writeEncodedText( std::string const& text ) { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while( pos != std::string::npos ) { - stream() << mtext.substr( 0, pos ); - - switch( mtext[pos] ) { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos+1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - bool m_tagIsOpen; bool m_needsNewline; std::vector m_tags; @@ -8052,32 +9033,44 @@ namespace Catch { }; } +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + namespace Catch { class XmlReporter : public StreamingReporterBase { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_sectionDepth( 0 ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - virtual ~XmlReporter(); + virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as an XML document"; } public: // StreamingReporterBase - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - virtual void noMatchingTestCases( std::string const& s ) { + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { StreamingReporterBase::noMatchingTestCases( s ); } - virtual void testRunStarting( TestRunInfo const& testInfo ) { + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); m_xml.setStream( stream ); m_xml.startElement( "Catch" ); @@ -8085,13 +9078,13 @@ namespace Catch { m_xml.writeAttribute( "name", m_config->name() ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); @@ -8099,7 +9092,7 @@ namespace Catch { m_testCaseTimer.start(); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) @@ -8108,9 +9101,9 @@ namespace Catch { } } - virtual void assertionStarting( AssertionInfo const& ) { } + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { const AssertionResult& assertionResult = assertionStats.assertionResult; // Print any info messages in tags. @@ -8181,7 +9174,7 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); @@ -8196,7 +9189,7 @@ namespace Catch { } } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); @@ -8207,7 +9200,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) @@ -8217,7 +9210,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) @@ -8248,28 +9241,24 @@ namespace Catch { JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - ~JunitReporter(); + virtual ~JunitReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) { + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); @@ -8277,25 +9266,25 @@ namespace Catch { CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } - virtual void testRunEndedCumulative() { + virtual void testRunEndedCumulative() CATCH_OVERRIDE { xml.endElement(); } @@ -8460,24 +9449,19 @@ namespace Catch { m_headerPrinted( false ) {} - virtual ~ConsoleReporter(); + virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - virtual void noMatchingTestCases( std::string const& spec ) { + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << "'" << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) { + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; @@ -8497,11 +9481,11 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) { + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -8523,11 +9507,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -8536,7 +9520,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; @@ -8700,12 +9684,7 @@ namespace Catch { stream << "\n" << getLineOfChars<'~'>() << "\n"; Colour colour( Colour::SecondaryText ); stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion.majorVersion << "." - << libraryVersion.minorVersion << " b" - << libraryVersion.buildNumber; - if( libraryVersion.branchName != std::string( "master" ) ) - stream << " (" << libraryVersion.branchName << ")"; - stream << " host application.\n" + << " is a Catch v" << libraryVersion << " host application.\n" << "Run with -? for options\n\n"; if( m_config->rngSeed() != 0 ) @@ -9180,8 +10159,14 @@ namespace Catch { } // end namespace Catch namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} @@ -9215,6 +10200,7 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} @@ -9226,6 +10212,13 @@ namespace Catch { Matchers::Impl::StdString::EndsWith::~EndsWith() {} void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } } #ifdef __clang__ @@ -9241,7 +10234,7 @@ namespace Catch { #ifndef __OBJC__ // Standard C/C++ main entry point -int main (int argc, char * const argv[]) { +int main (int argc, char * argv[]) { return Catch::Session().run( argc, argv ); } @@ -9279,8 +10272,9 @@ int main (int argc, char * const argv[]) { #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) @@ -9291,6 +10285,7 @@ int main (int argc, char * const argv[]) { #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) @@ -9306,6 +10301,7 @@ int main (int argc, char * const argv[]) { #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) @@ -9313,6 +10309,7 @@ int main (int argc, char * const argv[]) { #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) @@ -9332,11 +10329,11 @@ int main (int argc, char * const argv[]) { #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else @@ -9344,8 +10341,9 @@ int main (int argc, char * const argv[]) { #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) @@ -9354,8 +10352,9 @@ int main (int argc, char * const argv[]) { #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) @@ -9371,6 +10370,7 @@ int main (int argc, char * const argv[]) { #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) @@ -9378,6 +10378,7 @@ int main (int argc, char * const argv[]) { #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) @@ -9401,27 +10402,13 @@ int main (int argc, char * const argv[]) { #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define GIVEN( desc ) SECTION( " Given: " desc, "" ) -#define WHEN( desc ) SECTION( " When: " desc, "" ) -#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) -#define THEN( desc ) SECTION( " Then: " desc, "" ) -#define AND_THEN( desc ) SECTION( " And: " desc, "" ) +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; -// #included from: internal/catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 0150210..fcf96c8 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -11,20 +11,9 @@ #ifdef __GNUC__ #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wparentheses" #endif -#ifdef __llvm__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#pragma clang diagnostic ignored "-Wfloat-equal" -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - - #define CATCH_CONFIG_MAIN @@ -943,7 +932,7 @@ TEST_CASE("Parse floats with non-posix locale") std::cout << "Current locale: " << std::setlocale(LC_ALL, "en_ZA.utf8") << '\n'; chaiscript::ChaiScript chai; const double parsed = chai.eval("print(1.3); 1.3"); - CHECK(parsed == 1.3); + CHECK(parsed == Approx(1.3)); const std::string str = chai.eval("to_string(1.3)"); CHECK(str == "1.3"); } From ad7e2138d9e586571bb81aa61d1b4a2f65fe1511 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 17:39:32 -0700 Subject: [PATCH 10/33] Various Windows fixes --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 3 +- .../chaiscript/dispatchkit/boxed_number.hpp | 2 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 8 ++--- include/chaiscript/utility/json.hpp | 8 ++--- unittests/compiled_tests.cpp | 19 +++++++++--- unittests/type_info_test.cpp | 31 +++++++------------ 7 files changed, 37 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31452ba..61281cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,7 +158,7 @@ else() endif() if(MSVC) - add_definitions(/W4) + add_definitions(/W4 /w14545 /w34062 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928) # VS2013 doesn't have magic statics if (MSVC_VERSION STREQUAL "1800") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 1036a13..724185f 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -154,7 +154,8 @@ namespace chaiscript { } }; - for(char c = *t_str; (c = *t_str); ++t_str) { + for(; *t_str != '\0'; ++t_str) { + char c = *t_str; if (c == '.') { decimal_place = 10; } else if (c == 'e' || c == 'E') { diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 8a784ec..05f5ad6 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -43,7 +43,7 @@ namespace chaiscript // this is OK, so we're disabling size/and sign type warnings #ifdef CHAISCRIPT_MSVC #pragma warning(push) -#pragma warning(disable : 4244 4018 4389 4146 4365 4267) +#pragma warning(disable : 4244 4018 4389 4146 4365 4267 4242) #endif diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index c4d6b28..a272a07 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -591,14 +591,14 @@ namespace chaiscript } /// Adds a new scope to the stack - void new_scope(Stack_Holder &t_holder) + static void new_scope(Stack_Holder &t_holder) { get_stack_data(t_holder).emplace_back(); t_holder.call_params.emplace_back(); } /// Pops the current scope from the stack - void pop_scope(Stack_Holder &t_holder) + static void pop_scope(Stack_Holder &t_holder) { t_holder.call_params.pop_back(); StackData &stack = get_stack_data(t_holder); @@ -910,8 +910,8 @@ namespace chaiscript return m_conversions; } - bool is_attribute_call(const std::vector &t_funs, const std::vector &t_params, - bool t_has_params, const Type_Conversions_State &t_conversions) const + static bool is_attribute_call(const std::vector &t_funs, const std::vector &t_params, + bool t_has_params, const Type_Conversions_State &t_conversions) { if (!t_has_params || t_params.empty()) { return false; diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 1d9aac2..bdcbb7c 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -212,16 +212,16 @@ class JSON } template - JSON( T b, typename enable_if::value>::type* = 0 ) : Internal( b ), Type( Class::Boolean ){} + JSON( T b, typename enable_if::value>::type* = nullptr ) : Internal( b ), Type( Class::Boolean ){} template - JSON( T i, typename enable_if::value && !is_same::value>::type* = 0 ) : Internal( long(i) ), Type( Class::Integral ){} + JSON( T i, typename enable_if::value && !is_same::value>::type* = nullptr ) : Internal( long(i) ), Type( Class::Integral ){} template - JSON( T f, typename enable_if::value>::type* = 0 ) : Internal( double(f) ), Type( Class::Floating ){} + JSON( T f, typename enable_if::value>::type* = nullptr ) : Internal( double(f) ), Type( Class::Floating ){} template - JSON( T s, typename enable_if::value>::type* = 0 ) : Internal( string( s ) ), Type( Class::String ){} + JSON( T s, typename enable_if::value>::type* = nullptr ) : Internal( string( s ) ), Type( Class::String ){} JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){} diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index fcf96c8..551470e 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1,12 +1,10 @@ // All of these are necessary because of catch.hpp. It's OK, they'll be // caught in other cpp files if chaiscript causes them -#include -#include -#ifdef CHAISCRIPT_MSVC +#ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable : 4190 4640 28251 4702 6330) +#pragma warning(disable : 4242 28251) #endif #ifdef __GNUC__ @@ -15,6 +13,13 @@ #endif +#include +#include +#include + + + + #define CATCH_CONFIG_MAIN #include @@ -929,7 +934,11 @@ TEST_CASE("Map conversions") TEST_CASE("Parse floats with non-posix locale") { - std::cout << "Current locale: " << std::setlocale(LC_ALL, "en_ZA.utf8") << '\n'; +#ifdef CHAISCRIPT_MSVC + std::setlocale(LC_ALL, "en-ZA"); +#else + std::setlocale(LC_ALL, "en_ZA.utf8"); +#endif chaiscript::ChaiScript chai; const double parsed = chai.eval("print(1.3); 1.3"); CHECK(parsed == Approx(1.3)); diff --git a/unittests/type_info_test.cpp b/unittests/type_info_test.cpp index 9b9fd92..15bd633 100644 --- a/unittests/type_info_test.cpp +++ b/unittests/type_info_test.cpp @@ -1,30 +1,21 @@ // Tests to make sure that the order in which function dispatches occur is correct +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4242 28251) +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wparentheses" +#endif + + #include #include #include #include -#ifdef CHAISCRIPT_MSVC -#pragma warning(push) -#pragma warning(disable : 4190 4640 28251 4702 6330) -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#endif - -#ifdef __llvm__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wexit-time-destructors" -#pragma clang diagnostic ignored "-Wfloat-equal" -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - From 0cb4c18638927b3e3c847c2eac82233f9dc916eb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 18:22:21 -0700 Subject: [PATCH 11/33] Fix some more windows warnings --- unittests/compiled_tests.cpp | 2 +- unittests/type_info_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 551470e..2d70c8e 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -4,7 +4,7 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable : 4242 28251) +#pragma warning(disable : 4242 4702 6330 28251) #endif #ifdef __GNUC__ diff --git a/unittests/type_info_test.cpp b/unittests/type_info_test.cpp index 15bd633..a79fbb2 100644 --- a/unittests/type_info_test.cpp +++ b/unittests/type_info_test.cpp @@ -2,7 +2,7 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable : 4242 28251) +#pragma warning(disable : 4242 4702 6330 28251) #endif #ifdef __GNUC__ From 765e6ed8df8188dfd505de5f305a8eb183d3b831 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 18:26:14 -0700 Subject: [PATCH 12/33] Update release notes for 5.8.1 --- releasenotes.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/releasenotes.md b/releasenotes.md index 993f93d..ea83197 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,11 @@ Notes: ======= -Current Version: 5.8.0 +Current Version: 5.8.1 + +### Changes since 5.8.0 +* Fix parsing of floats to be locale independent #250 +* Various warning fixes on various platforms + ### Changes since 5.7.1 * Make all parser iterator operations range checked From a0ee8d1137ac48374363cc76b8390cfc54e100b2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 21:48:08 -0700 Subject: [PATCH 13/33] Address more catch/msvc warnings --- unittests/compiled_tests.cpp | 2 +- unittests/type_info_test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 2d70c8e..3c49ced 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -4,7 +4,7 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable : 4242 4702 6330 28251) +#pragma warning(disable : 4062 4242 4640 4702 6330 28251) #endif #ifdef __GNUC__ diff --git a/unittests/type_info_test.cpp b/unittests/type_info_test.cpp index a79fbb2..d61dd88 100644 --- a/unittests/type_info_test.cpp +++ b/unittests/type_info_test.cpp @@ -2,7 +2,7 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable : 4242 4702 6330 28251) +#pragma warning(disable : 4062 4242 4640 4702 6330 28251) #endif #ifdef __GNUC__ From c24004c70e9e10199ac8748aa768ce2df64b0f8c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 4 Mar 2016 22:09:26 -0700 Subject: [PATCH 14/33] Disable more warnings for catch/gcc --- unittests/compiled_tests.cpp | 1 + unittests/type_info_test.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 3c49ced..40a6c88 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -9,6 +9,7 @@ #ifdef __GNUC__ #pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wparentheses" #endif diff --git a/unittests/type_info_test.cpp b/unittests/type_info_test.cpp index d61dd88..57f02f3 100644 --- a/unittests/type_info_test.cpp +++ b/unittests/type_info_test.cpp @@ -7,6 +7,7 @@ #ifdef __GNUC__ #pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wparentheses" #endif From 83b966df470f6762bdf629d88db7d4a09ad276e4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 07:45:33 -0700 Subject: [PATCH 15/33] Address g++4.8 warnings --- unittests/catch.hpp | 2 +- unittests/compiled_tests.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/unittests/catch.hpp b/unittests/catch.hpp index 5b9bfc2..2554d91 100644 --- a/unittests/catch.hpp +++ b/unittests/catch.hpp @@ -149,7 +149,7 @@ # endif # if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "gcc diagnostic ignored \"-Wparentheses\"" ) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) # endif // - otherwise more recent versions define __cplusplus >= 201103L diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 40a6c88..edc62e2 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -7,6 +7,7 @@ #pragma warning(disable : 4062 4242 4640 4702 6330 28251) #endif + #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" From 594958ea8bb7f692b78bfbae92330676245e0714 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 07:46:28 -0700 Subject: [PATCH 16/33] Address MSVC2013 specific warnings --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 61281cb..b00ce4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,11 +158,14 @@ else() endif() if(MSVC) - add_definitions(/W4 /w14545 /w34062 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928) + add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928) - # VS2013 doesn't have magic statics if (MSVC_VERSION STREQUAL "1800") + # VS2013 doesn't have magic statics add_definitions(/w44640) + else() + # enum warnings are too noisy on MSVC2013 + add_definitions(/w34062) endif() add_definitions(/bigobj) From 539ee3c84f50da96767b7741b1879a2bfdddaa10 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 10:44:40 -0700 Subject: [PATCH 17/33] Ignore unknown pragmas in older apple clang --- include/chaiscript/dispatchkit/boxed_number.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 05f5ad6..72b4e7e 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -49,6 +49,7 @@ namespace chaiscript #ifdef __GNUC__ #pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wpragmas" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wfloat-equal" From 71c67bc76342bb3cb13208b56246d91fac90fd08 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 12:04:30 -0700 Subject: [PATCH 18/33] Move debug over to windows build --- .decent_ci-MacOS.yaml | 4 ---- .decent_ci-Windows.yaml | 7 +++++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.decent_ci-MacOS.yaml b/.decent_ci-MacOS.yaml index f297a14..e183000 100644 --- a/.decent_ci-MacOS.yaml +++ b/.decent_ci-MacOS.yaml @@ -2,8 +2,4 @@ compilers: - name: clang cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA build_package_generator: TBZ2 - - name: clang - build_type: Debug - cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - skip_packaging: true diff --git a/.decent_ci-Windows.yaml b/.decent_ci-Windows.yaml index 7f36f91..e4bea21 100644 --- a/.decent_ci-Windows.yaml +++ b/.decent_ci-Windows.yaml @@ -17,4 +17,11 @@ compilers: version: 12 architecture: Win64 cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + - name: Visual Studio + version: 14 + build_type: Debug + architecture: Win64 + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + compiler_extra_flags: /analyze + skip_packaging: true From cf5913f8906f91021359c9ebf2c3cbec0bc71e10 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 17:45:11 -0700 Subject: [PATCH 19/33] Add gitter appveyor webhook --- appveyor.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c402efe..50c5921 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 5.7.2.{build} +version: 5.8.x.{build} os: Visual Studio 2015 environment: matrix: @@ -14,3 +14,9 @@ build_script: cmake --build . --config Debug test_script: - cmd: ctest -C Debug +notifications: +- provider: Webhook + url: https://webhooks.gitter.im/e/9ff725a985b5679d1d5d + on_build_success: true + on_build_failure: true + on_build_status_changed: false From 467392e17dff0a7c3b79791888426c002037b625 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 18:26:15 -0700 Subject: [PATCH 20/33] Update readme.md --- readme.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/readme.md b/readme.md index 160662a..339b805 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,8 @@ + + + + + Master Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=master)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=master)](http://codecov.io/github/ChaiScript/ChaiScript?branch=master) Develop Status: [![Linux Build Status](https://travis-ci.org/ChaiScript/ChaiScript.png?branch=develop)](https://travis-ci.org/ChaiScript/ChaiScript) [![Windows Build status](https://ci.appveyor.com/api/projects/status/6u3r4s81kkjqmsqw/branch/develop?svg=true)](https://ci.appveyor.com/project/lefticus/chaiscript/branch/develop) [![codecov.io](http://codecov.io/github/ChaiScript/ChaiScript/coverage.svg?branch=develop)](http://codecov.io/github/ChaiScript/ChaiScript?branch=develop) From e0143081544996a614686f871b7f4a335728d3db Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 5 Mar 2016 18:32:44 -0700 Subject: [PATCH 21/33] Create supporters.md --- supporters.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 supporters.md diff --git a/supporters.md b/supporters.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/supporters.md @@ -0,0 +1 @@ + From fe8f571f47745f4a2119d11e40e64053c5db448d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 7 Mar 2016 07:16:57 -0700 Subject: [PATCH 22/33] Add test_module to set of required modules during build --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50b5e3e..621b07d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,6 +271,9 @@ endif() if(BUILD_MODULES) + add_library(test_module MODULE src/test_module.cpp) + target_link_libraries(test_module ${LIBS}) + add_library(stl_extra MODULE src/stl_extra.cpp) target_link_libraries(stl_extra ${LIBS}) @@ -456,9 +459,6 @@ if(BUILD_TESTING) target_link_libraries(multifile_test ${LIBS}) add_test(NAME MultiFile_Test COMMAND multifile_test) - add_library(test_module MODULE src/test_module.cpp) - target_link_libraries(test_module ${LIBS}) - install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript) endif() endif() From 019c6b2830dc4aaa149414e7dd9b483ebc7aaf4a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 7 Mar 2016 15:36:12 -0700 Subject: [PATCH 23/33] Cleanup of ChaiScript_Parser From episode 1 of C++ Weekly. --- .../chaiscript/language/chaiscript_parser.hpp | 228 ++++++++++-------- 1 file changed, 124 insertions(+), 104 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index f9e567b..6cec512 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -58,15 +58,130 @@ namespace chaiscript class ChaiScript_Parser { - std::string m_multiline_comment_begin; - std::string m_multiline_comment_end; - std::string m_singleline_comment; + static constexpr const char * const m_multiline_comment_begin = "/*"; + static constexpr const char * const m_multiline_comment_end = "*/"; + static constexpr const char * const m_singleline_comment = "//"; + + + static std::array, detail::max_alphabet> build_alphabet() + { + std::array, detail::max_alphabet> alphabet = {}; + + for (auto &alpha : alphabet) { + alpha.fill(false); + } + + alphabet[detail::symbol_alphabet][static_cast('?')]=true; + alphabet[detail::symbol_alphabet][static_cast('+')]=true; + alphabet[detail::symbol_alphabet][static_cast('-')]=true; + alphabet[detail::symbol_alphabet][static_cast('*')]=true; + alphabet[detail::symbol_alphabet][static_cast('/')]=true; + alphabet[detail::symbol_alphabet][static_cast('|')]=true; + alphabet[detail::symbol_alphabet][static_cast('&')]=true; + alphabet[detail::symbol_alphabet][static_cast('^')]=true; + alphabet[detail::symbol_alphabet][static_cast('=')]=true; + alphabet[detail::symbol_alphabet][static_cast('.')]=true; + alphabet[detail::symbol_alphabet][static_cast('<')]=true; + alphabet[detail::symbol_alphabet][static_cast('>')]=true; + + for ( int c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } + for ( int c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } + for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } + alphabet[detail::keyword_alphabet][static_cast('_')]=true; + + for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::int_alphabet][c]=true; } + for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::float_alphabet][c]=true; } + alphabet[detail::float_alphabet][static_cast('.')]=true; + + for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } + for ( int c = 'a' ; c <= 'f' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } + for ( int c = 'A' ; c <= 'F' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } + + alphabet[detail::x_alphabet][static_cast('x')]=true; + alphabet[detail::x_alphabet][static_cast('X')]=true; + + for ( int c = '0' ; c <= '1' ; ++c ) { alphabet[detail::bin_alphabet][c]=true; } + alphabet[detail::b_alphabet][static_cast('b')]=true; + alphabet[detail::b_alphabet][static_cast('B')]=true; + + for ( int c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; } + for ( int c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; } + alphabet[detail::id_alphabet][static_cast('_')] = true; + + alphabet[detail::white_alphabet][static_cast(' ')]=true; + alphabet[detail::white_alphabet][static_cast('\t')]=true; + + alphabet[detail::int_suffix_alphabet][static_cast('l')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('L')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('u')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('U')] = true; + + alphabet[detail::float_suffix_alphabet][static_cast('l')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('L')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('f')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('F')] = true; + + return alphabet; + } + + static const std::array, detail::max_alphabet> &create_alphabet() + { + static const auto alpha = build_alphabet(); + return alpha; + } + + const std::array, detail::max_alphabet> &m_alphabet = create_alphabet(); + + static const std::vector> build_operator_matches() { + std::vector> operator_matches; + operator_matches.emplace_back(std::initializer_list({"?"})); + operator_matches.emplace_back(std::initializer_list({"||"})); + operator_matches.emplace_back(std::initializer_list({"&&"})); + operator_matches.emplace_back(std::initializer_list({"|"})); + operator_matches.emplace_back(std::initializer_list({"^"})); + operator_matches.emplace_back(std::initializer_list({"&"})); + operator_matches.emplace_back(std::initializer_list({"==", "!="})); + operator_matches.emplace_back(std::initializer_list({"<", "<=", ">", ">="})); + operator_matches.emplace_back(std::initializer_list({"<<", ">>"})); + + //We share precedence here but then separate them later + operator_matches.emplace_back(std::initializer_list({"+", "-"})); + + //We share precedence here but then separate them later + operator_matches.emplace_back(std::initializer_list({"*", "/", "%"})); + + return operator_matches; + }; + + static const std::vector> &create_operator_matches() { + static const auto operator_matches = build_operator_matches(); + return operator_matches; + } + + const std::vector> &m_operator_matches = create_operator_matches(); + + static const std::array &create_operators() { + static const std::array operators = {{ + AST_Node_Type::Ternary_Cond, + AST_Node_Type::Logical_Or, + AST_Node_Type::Logical_And, + AST_Node_Type::Bitwise_Or, + AST_Node_Type::Bitwise_Xor, + AST_Node_Type::Bitwise_And, + AST_Node_Type::Equality, + AST_Node_Type::Comparison, + AST_Node_Type::Shift, + AST_Node_Type::Addition, + AST_Node_Type::Multiplication + }}; + return operators; + } + + const std::array &m_operators = create_operators(); + std::shared_ptr m_filename; std::vector m_match_stack; - bool m_alphabet[detail::max_alphabet][detail::lengthof_alphabet]; - std::vector> m_operator_matches; - std::vector m_operators; struct Position { @@ -171,108 +286,13 @@ namespace chaiscript public: ChaiScript_Parser() - : m_multiline_comment_begin("/*"), - m_multiline_comment_end("*/"), - m_singleline_comment("//") { m_match_stack.reserve(2); - setup_operators(); } ChaiScript_Parser(const ChaiScript_Parser &) = delete; ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete; - void setup_operators() - { - m_operators.emplace_back(AST_Node_Type::Ternary_Cond); - m_operator_matches.emplace_back(std::initializer_list({"?"})); - - m_operators.emplace_back(AST_Node_Type::Logical_Or); - m_operator_matches.emplace_back(std::initializer_list({"||"})); - - m_operators.emplace_back(AST_Node_Type::Logical_And); - m_operator_matches.emplace_back(std::initializer_list({"&&"})); - - m_operators.emplace_back(AST_Node_Type::Bitwise_Or); - m_operator_matches.emplace_back(std::initializer_list({"|"})); - - m_operators.emplace_back(AST_Node_Type::Bitwise_Xor); - m_operator_matches.emplace_back(std::initializer_list({"^"})); - - m_operators.emplace_back(AST_Node_Type::Bitwise_And); - m_operator_matches.emplace_back(std::initializer_list({"&"})); - - m_operators.emplace_back(AST_Node_Type::Equality); - m_operator_matches.emplace_back(std::initializer_list({"==", "!="})); - - m_operators.emplace_back(AST_Node_Type::Comparison); - m_operator_matches.emplace_back(std::initializer_list({"<", "<=", ">", ">="})); - - m_operators.emplace_back(AST_Node_Type::Shift); - m_operator_matches.emplace_back(std::initializer_list({"<<", ">>"})); - - //We share precedence here but then separate them later - m_operators.emplace_back(AST_Node_Type::Addition); - m_operator_matches.emplace_back(std::initializer_list({"+", "-"})); - - //We share precedence here but then separate them later - m_operators.emplace_back(AST_Node_Type::Multiplication); - m_operator_matches.emplace_back(std::initializer_list({"*", "/", "%"})); - - for (auto & elem : m_alphabet) { - std::fill(std::begin(elem), std::end(elem), false); - } - - m_alphabet[detail::symbol_alphabet][static_cast('?')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('+')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('-')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('*')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('/')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('|')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('&')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('^')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('=')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('.')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('<')]=true; - m_alphabet[detail::symbol_alphabet][static_cast('>')]=true; - - for ( int c = 'a' ; c <= 'z' ; ++c ) { m_alphabet[detail::keyword_alphabet][c]=true; } - for ( int c = 'A' ; c <= 'Z' ; ++c ) { m_alphabet[detail::keyword_alphabet][c]=true; } - for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::keyword_alphabet][c]=true; } - m_alphabet[detail::keyword_alphabet][static_cast('_')]=true; - - for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::int_alphabet][c]=true; } - for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::float_alphabet][c]=true; } - m_alphabet[detail::float_alphabet][static_cast('.')]=true; - - for ( int c = '0' ; c <= '9' ; ++c ) { m_alphabet[detail::hex_alphabet][c]=true; } - for ( int c = 'a' ; c <= 'f' ; ++c ) { m_alphabet[detail::hex_alphabet][c]=true; } - for ( int c = 'A' ; c <= 'F' ; ++c ) { m_alphabet[detail::hex_alphabet][c]=true; } - - m_alphabet[detail::x_alphabet][static_cast('x')]=true; - m_alphabet[detail::x_alphabet][static_cast('X')]=true; - - for ( int c = '0' ; c <= '1' ; ++c ) { m_alphabet[detail::bin_alphabet][c]=true; } - m_alphabet[detail::b_alphabet][static_cast('b')]=true; - m_alphabet[detail::b_alphabet][static_cast('B')]=true; - - for ( int c = 'a' ; c <= 'z' ; ++c ) { m_alphabet[detail::id_alphabet][c]=true; } - for ( int c = 'A' ; c <= 'Z' ; ++c ) { m_alphabet[detail::id_alphabet][c]=true; } - m_alphabet[detail::id_alphabet][static_cast('_')] = true; - - m_alphabet[detail::white_alphabet][static_cast(' ')]=true; - m_alphabet[detail::white_alphabet][static_cast('\t')]=true; - - m_alphabet[detail::int_suffix_alphabet][static_cast('l')] = true; - m_alphabet[detail::int_suffix_alphabet][static_cast('L')] = true; - m_alphabet[detail::int_suffix_alphabet][static_cast('u')] = true; - m_alphabet[detail::int_suffix_alphabet][static_cast('U')] = true; - - m_alphabet[detail::float_suffix_alphabet][static_cast('l')] = true; - m_alphabet[detail::float_suffix_alphabet][static_cast('L')] = true; - m_alphabet[detail::float_suffix_alphabet][static_cast('f')] = true; - m_alphabet[detail::float_suffix_alphabet][static_cast('F')] = true; - } /// test a char in an m_alphabet bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast(c)]; } @@ -423,16 +443,16 @@ namespace chaiscript /// Skips any multi-line or single-line comment bool SkipComment() { - if (Symbol_(m_multiline_comment_begin.c_str())) { + if (Symbol_(m_multiline_comment_begin)) { while (m_position.has_more()) { - if (Symbol_(m_multiline_comment_end.c_str())) { + if (Symbol_(m_multiline_comment_end)) { break; } else if (!Eol_()) { ++m_position; } } return true; - } else if (Symbol_(m_singleline_comment.c_str())) { + } else if (Symbol_(m_singleline_comment)) { while (m_position.has_more()) { if (Symbol_("\r\n")) { m_position -= 2; From 85163e08ccd707b1cb76cfa4d62c064da955eae1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 7 Mar 2016 16:19:40 -0700 Subject: [PATCH 24/33] Add missing header include --- include/chaiscript/dispatchkit/proxy_functions_detail.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index c4d30ff..7b36c09 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "../chaiscript_defines.hpp" #include "boxed_cast.hpp" From cfc8a3d2144d8e63e6dfe7d43dbf436ed70dcb40 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 7 Mar 2016 21:24:21 -0700 Subject: [PATCH 25/33] Warning cleanups and simplification --- .../chaiscript/language/chaiscript_parser.hpp | 130 ++++++++---------- 1 file changed, 61 insertions(+), 69 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 6cec512..bd18a6d 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -58,11 +58,6 @@ namespace chaiscript class ChaiScript_Parser { - static constexpr const char * const m_multiline_comment_begin = "/*"; - static constexpr const char * const m_multiline_comment_end = "*/"; - static constexpr const char * const m_singleline_comment = "//"; - - static std::array, detail::max_alphabet> build_alphabet() { std::array, detail::max_alphabet> alphabet = {}; @@ -71,55 +66,55 @@ namespace chaiscript alpha.fill(false); } - alphabet[detail::symbol_alphabet][static_cast('?')]=true; - alphabet[detail::symbol_alphabet][static_cast('+')]=true; - alphabet[detail::symbol_alphabet][static_cast('-')]=true; - alphabet[detail::symbol_alphabet][static_cast('*')]=true; - alphabet[detail::symbol_alphabet][static_cast('/')]=true; - alphabet[detail::symbol_alphabet][static_cast('|')]=true; - alphabet[detail::symbol_alphabet][static_cast('&')]=true; - alphabet[detail::symbol_alphabet][static_cast('^')]=true; - alphabet[detail::symbol_alphabet][static_cast('=')]=true; - alphabet[detail::symbol_alphabet][static_cast('.')]=true; - alphabet[detail::symbol_alphabet][static_cast('<')]=true; - alphabet[detail::symbol_alphabet][static_cast('>')]=true; + alphabet[detail::symbol_alphabet][static_cast('?')]=true; + alphabet[detail::symbol_alphabet][static_cast('+')]=true; + alphabet[detail::symbol_alphabet][static_cast('-')]=true; + alphabet[detail::symbol_alphabet][static_cast('*')]=true; + alphabet[detail::symbol_alphabet][static_cast('/')]=true; + alphabet[detail::symbol_alphabet][static_cast('|')]=true; + alphabet[detail::symbol_alphabet][static_cast('&')]=true; + alphabet[detail::symbol_alphabet][static_cast('^')]=true; + alphabet[detail::symbol_alphabet][static_cast('=')]=true; + alphabet[detail::symbol_alphabet][static_cast('.')]=true; + alphabet[detail::symbol_alphabet][static_cast('<')]=true; + alphabet[detail::symbol_alphabet][static_cast('>')]=true; - for ( int c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } - for ( int c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } - for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } - alphabet[detail::keyword_alphabet][static_cast('_')]=true; + for ( size_t c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } + for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } + for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; } + alphabet[detail::keyword_alphabet][static_cast('_')]=true; - for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::int_alphabet][c]=true; } - for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::float_alphabet][c]=true; } - alphabet[detail::float_alphabet][static_cast('.')]=true; + for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::int_alphabet][c]=true; } + for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::float_alphabet][c]=true; } + alphabet[detail::float_alphabet][static_cast('.')]=true; - for ( int c = '0' ; c <= '9' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } - for ( int c = 'a' ; c <= 'f' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } - for ( int c = 'A' ; c <= 'F' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } + for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } + for ( size_t c = 'a' ; c <= 'f' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } + for ( size_t c = 'A' ; c <= 'F' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; } - alphabet[detail::x_alphabet][static_cast('x')]=true; - alphabet[detail::x_alphabet][static_cast('X')]=true; + alphabet[detail::x_alphabet][static_cast('x')]=true; + alphabet[detail::x_alphabet][static_cast('X')]=true; - for ( int c = '0' ; c <= '1' ; ++c ) { alphabet[detail::bin_alphabet][c]=true; } - alphabet[detail::b_alphabet][static_cast('b')]=true; - alphabet[detail::b_alphabet][static_cast('B')]=true; + for ( size_t c = '0' ; c <= '1' ; ++c ) { alphabet[detail::bin_alphabet][c]=true; } + alphabet[detail::b_alphabet][static_cast('b')]=true; + alphabet[detail::b_alphabet][static_cast('B')]=true; - for ( int c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; } - for ( int c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; } - alphabet[detail::id_alphabet][static_cast('_')] = true; + for ( size_t c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; } + for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; } + alphabet[detail::id_alphabet][static_cast('_')] = true; - alphabet[detail::white_alphabet][static_cast(' ')]=true; - alphabet[detail::white_alphabet][static_cast('\t')]=true; + alphabet[detail::white_alphabet][static_cast(' ')]=true; + alphabet[detail::white_alphabet][static_cast('\t')]=true; - alphabet[detail::int_suffix_alphabet][static_cast('l')] = true; - alphabet[detail::int_suffix_alphabet][static_cast('L')] = true; - alphabet[detail::int_suffix_alphabet][static_cast('u')] = true; - alphabet[detail::int_suffix_alphabet][static_cast('U')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('l')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('L')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('u')] = true; + alphabet[detail::int_suffix_alphabet][static_cast('U')] = true; - alphabet[detail::float_suffix_alphabet][static_cast('l')] = true; - alphabet[detail::float_suffix_alphabet][static_cast('L')] = true; - alphabet[detail::float_suffix_alphabet][static_cast('f')] = true; - alphabet[detail::float_suffix_alphabet][static_cast('F')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('l')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('L')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('f')] = true; + alphabet[detail::float_suffix_alphabet][static_cast('F')] = true; return alphabet; } @@ -130,35 +125,26 @@ namespace chaiscript return alpha; } - const std::array, detail::max_alphabet> &m_alphabet = create_alphabet(); - - static const std::vector> build_operator_matches() { - std::vector> operator_matches; - operator_matches.emplace_back(std::initializer_list({"?"})); - operator_matches.emplace_back(std::initializer_list({"||"})); - operator_matches.emplace_back(std::initializer_list({"&&"})); - operator_matches.emplace_back(std::initializer_list({"|"})); - operator_matches.emplace_back(std::initializer_list({"^"})); - operator_matches.emplace_back(std::initializer_list({"&"})); - operator_matches.emplace_back(std::initializer_list({"==", "!="})); - operator_matches.emplace_back(std::initializer_list({"<", "<=", ">", ">="})); - operator_matches.emplace_back(std::initializer_list({"<<", ">>"})); - - //We share precedence here but then separate them later - operator_matches.emplace_back(std::initializer_list({"+", "-"})); - - //We share precedence here but then separate them later - operator_matches.emplace_back(std::initializer_list({"*", "/", "%"})); - - return operator_matches; - }; static const std::vector> &create_operator_matches() { - static const auto operator_matches = build_operator_matches(); + static const std::vector> operator_matches { + {"?"}, + {"||"}, + {"&&"}, + {"|"}, + {"^"}, + {"&"}, + {"==", "!="}, + {"<", "<=", ">", ">="}, + {"<<", ">>"}, + //We share precedence here but then separate them later + {"+", "-"}, + {"*", "/", "%"} + }; + return operator_matches; } - const std::vector> &m_operator_matches = create_operator_matches(); static const std::array &create_operators() { static const std::array operators = {{ @@ -177,6 +163,12 @@ namespace chaiscript return operators; } + static constexpr const char * const m_multiline_comment_begin = "/*"; + static constexpr const char * const m_multiline_comment_end = "*/"; + static constexpr const char * const m_singleline_comment = "//"; + + const std::array, detail::max_alphabet> &m_alphabet = create_alphabet(); + const std::vector> &m_operator_matches = create_operator_matches(); const std::array &m_operators = create_operators(); std::shared_ptr m_filename; From 978f80751fefeca27dfce9777f340d660e13626d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 10 Mar 2016 12:33:07 -0700 Subject: [PATCH 26/33] Update proxy_functions_detail to c++14 --- .../dispatchkit/proxy_functions_detail.hpp | 45 ++++--------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 7b36c09..f8416a0 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -67,57 +67,31 @@ namespace chaiscript } - - template - struct Indexes - { - }; - - template - struct Make_Indexes - { - typedef typename Make_Indexes::indexes indexes; - }; - - template - struct Make_Indexes<0, I...> - { - typedef Indexes indexes; - }; - - - /** * Used by Proxy_Function_Impl to determine if it is equivalent to another * Proxy_Function_Impl object. This function is primarily used to prevent * registration of two functions with the exact same signatures */ - template - bool compare_types_cast(Indexes, Ret (*)(Params...), + template + bool compare_types_cast(Ret (*)(Params...), const std::vector ¶ms, const Type_Conversions_State &t_conversions) { try { + int i = 0; (void)params; (void)t_conversions; - (void)std::initializer_list{(boxed_cast(params[I], &t_conversions), 0)...}; + // this is ok because the order of evaluation of initializer lists is well defined + (void)std::initializer_list{(boxed_cast(params[i++], &t_conversions), 0)...}; return true; } catch (const exception::bad_boxed_cast &) { return false; } - - } - - template - bool compare_types_cast(Ret (*f)(Params...), - const std::vector ¶ms, const Type_Conversions_State &t_conversions) - { - typedef typename Make_Indexes::indexes indexes; - return compare_types_cast(indexes(), f, params, t_conversions); } template - Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, Indexes, const Callable &f, - const std::vector ¶ms, const Type_Conversions_State &t_conversions) + Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, + std::index_sequence, const Callable &f, + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { (void)params; (void)t_conversions; return f(boxed_cast(params[I], &t_conversions)...); @@ -134,8 +108,7 @@ namespace chaiscript Ret call_func(const chaiscript::dispatch::detail::Function_Signature &sig, const Callable &f, const std::vector ¶ms, const Type_Conversions_State &t_conversions) { - typedef typename Make_Indexes::indexes indexes; - return call_func(sig, indexes(), f, params, t_conversions); + return call_func(sig, std::index_sequence_for{}, f, params, t_conversions); } } From 91ba9e25c0c208818c77e1e1319641f79f3ad415 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 10 Mar 2016 13:53:24 -0700 Subject: [PATCH 27/33] Remove g++ 4.8 from builds --- .decent_ci-Linux.yaml | 6 +----- .travis.yml | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 4d777eb..4215352 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -29,17 +29,13 @@ compilers: version: "3.7" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=ON -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON - - name: "gcc" - version: "4.8" - skip_packaging: true - cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON - collect_performance_results: true - name: "gcc" version: "4.9" cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON collect_performance_results: true - name: "gcc" version: "4.9" + skip_packaging: true build_tag: "NoThreads" cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF collect_performance_results: true diff --git a/.travis.yml b/.travis.yml index 2c962bd..f3db01d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ compiler: - gcc env: matrix: - - GCC_VER="4.8" - GCC_VER="4.9" - GCC_VER="5" From 11ee71ba27fcbd6b1d4fcf25deb2e2989cf7e05d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 10 Mar 2016 14:45:07 -0700 Subject: [PATCH 28/33] Fix index type --- include/chaiscript/dispatchkit/proxy_functions_detail.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index f8416a0..96f8896 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -77,7 +77,7 @@ namespace chaiscript const std::vector ¶ms, const Type_Conversions_State &t_conversions) { try { - int i = 0; + std::vector::size_type i = 0; (void)params; (void)t_conversions; // this is ok because the order of evaluation of initializer lists is well defined (void)std::initializer_list{(boxed_cast(params[i++], &t_conversions), 0)...}; From cd1b3f88879e39d267d4ac2964f0a00d502507c9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 09:24:00 -0700 Subject: [PATCH 29/33] Virtual / override / public cleanups --- .../chaiscript/dispatchkit/dispatchkit.hpp | 14 +- .../dispatchkit/proxy_functions.hpp | 83 ++-- .../chaiscript/language/chaiscript_eval.hpp | 365 +++++++----------- 3 files changed, 184 insertions(+), 278 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 7b0fa57..d98400b 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -267,7 +267,7 @@ namespace chaiscript /// A Proxy_Function implementation that is able to take /// a vector of Proxy_Functions and perform a dispatch on them. It is /// used specifically in the case of dealing with Function object variables - class Dispatch_Function : public dispatch::Proxy_Function_Base + class Dispatch_Function final : public dispatch::Proxy_Function_Base { public: Dispatch_Function(std::vector t_funcs) @@ -276,7 +276,7 @@ namespace chaiscript { } - virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const override + bool operator==(const dispatch::Proxy_Function_Base &rhs) const override { try { const auto &dispatch_fun = dynamic_cast(rhs); @@ -286,9 +286,7 @@ namespace chaiscript } } - virtual ~Dispatch_Function() {} - - virtual std::vector get_contained_functions() const override + std::vector get_contained_functions() const override { return std::vector(m_funcs.begin(), m_funcs.end()); } @@ -314,19 +312,19 @@ namespace chaiscript return arity; } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return std::any_of(m_funcs.cbegin(), m_funcs.cend(), [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); } - virtual std::string annotation() const override + std::string annotation() const override { return "Multiple method dispatch function wrapper."; } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return dispatch::dispatch(m_funcs, params, t_conversions); } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index abf5a33..507abb6 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -145,7 +145,7 @@ namespace chaiscript class Proxy_Function_Base { public: - virtual ~Proxy_Function_Base() {} + virtual ~Proxy_Function_Base() = default; Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Type_Conversions_State &t_conversions) const { @@ -248,7 +248,8 @@ namespace chaiscript } - static bool compare_types(const std::vector &tis, const std::vector &bvs, const Type_Conversions_State &t_conversions) + static bool compare_types(const std::vector &tis, const std::vector &bvs, + const Type_Conversions_State &t_conversions) { if (tis.size() - 1 != bvs.size()) { @@ -288,8 +289,7 @@ namespace chaiscript guard_error(const guard_error &) = default; - virtual ~guard_error() noexcept - { } + virtual ~guard_error() noexcept = default; }; } @@ -314,7 +314,6 @@ namespace chaiscript { } - virtual ~Dynamic_Proxy_Function() {} virtual bool operator==(const Proxy_Function_Base &rhs) const override { @@ -394,7 +393,7 @@ namespace chaiscript template - class Dynamic_Proxy_Function_Impl : public Dynamic_Proxy_Function + class Dynamic_Proxy_Function_Impl final : public Dynamic_Proxy_Function { public: Dynamic_Proxy_Function_Impl( @@ -415,11 +414,9 @@ namespace chaiscript { } - virtual ~Dynamic_Proxy_Function_Impl() {} - protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { if (call_match(params, t_conversions) && test_guard(params, t_conversions)) { @@ -430,7 +427,6 @@ namespace chaiscript } private: - Callable m_f; }; @@ -451,7 +447,7 @@ namespace chaiscript /// and substitutes bound parameters into the parameter list /// at runtime, when call() is executed. /// it is used for bind(function, param1, _, param2) style calls - class Bound_Function : public Proxy_Function_Base + class Bound_Function final : public Proxy_Function_Base { public: Bound_Function(const Const_Proxy_Function &t_f, @@ -462,19 +458,18 @@ namespace chaiscript assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast(m_args.size())); } - virtual bool operator==(const Proxy_Function_Base &t_f) const override + bool operator==(const Proxy_Function_Base &t_f) const override { return &t_f == this; } - virtual ~Bound_Function() {} - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return m_f->call_match(build_param_list(vals), t_conversions); } - virtual std::vector get_contained_functions() const override + std::vector get_contained_functions() const override { return std::vector{m_f}; } @@ -524,7 +519,7 @@ namespace chaiscript if (t_f->get_arity() < 0) { return std::vector(); } - std::vector types = t_f->get_param_types(); + const auto types = t_f->get_param_types(); assert(types.size() == t_args.size() + 1); // this analysis warning is invalid in MSVC12 and doesn't exist in MSVC14 @@ -559,16 +554,15 @@ namespace chaiscript { } - virtual ~Proxy_Function_Impl_Base() {} - - virtual std::string annotation() const override + std::string annotation() const override { return ""; } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { - return static_cast(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions)); + return static_cast(vals.size()) == get_arity() + && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions)); } virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const = 0; @@ -578,7 +572,7 @@ namespace chaiscript /// For any callable object template - class Proxy_Function_Callable_Impl : public Proxy_Function_Impl_Base + class Proxy_Function_Callable_Impl final : public Proxy_Function_Impl_Base { public: Proxy_Function_Callable_Impl(Callable f) @@ -587,21 +581,19 @@ namespace chaiscript { } - virtual ~Proxy_Function_Callable_Impl() {} - - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } - virtual bool operator==(const Proxy_Function_Base &t_func) const override + bool operator==(const Proxy_Function_Base &t_func) const override { return dynamic_cast *>(&t_func) != nullptr; } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { typedef typename detail::Function_Signature::Return_Type Return_Type; return detail::Do_Call::template go(m_f, params, t_conversions); @@ -620,16 +612,11 @@ namespace chaiscript { } - virtual ~Assignable_Proxy_Function() {} - - - virtual void assign(const std::shared_ptr &t_rhs) = 0; - - + virtual void assign(const std::shared_ptr &t_rhs) = 0; }; template - class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function + class Assignable_Proxy_Function_Impl final : public Assignable_Proxy_Function { public: Assignable_Proxy_Function_Impl(std::reference_wrapper> t_f, std::shared_ptr> t_ptr) @@ -639,14 +626,12 @@ namespace chaiscript assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get()); } - virtual ~Assignable_Proxy_Function_Impl() {} - - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } - virtual bool operator==(const Proxy_Function_Base &t_func) const override + bool operator==(const Proxy_Function_Base &t_func) const override { return dynamic_cast *>(&t_func) != nullptr; } @@ -656,12 +641,12 @@ namespace chaiscript return m_f.get(); } - virtual void assign(const std::shared_ptr &t_rhs) override { + void assign(const std::shared_ptr &t_rhs) override { m_f.get() = dispatch::functor(t_rhs, nullptr); } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return detail::Do_Call::result_type>::template go(m_f.get(), params, t_conversions); } @@ -671,9 +656,11 @@ namespace chaiscript std::reference_wrapper> m_f; std::shared_ptr> m_shared_ptr_holder; }; + + /// Attribute getter Proxy_Function implementation template - class Attribute_Access : public Proxy_Function_Base + class Attribute_Access final : public Proxy_Function_Base { public: Attribute_Access(T Class::* t_attr) @@ -682,11 +669,9 @@ namespace chaiscript { } - virtual ~Attribute_Access() {} + bool is_attribute_function() const override { return true; } - virtual bool is_attribute_function() const override { return true; } - - virtual bool operator==(const Proxy_Function_Base &t_func) const override + bool operator==(const Proxy_Function_Base &t_func) const override { const Attribute_Access * aa = dynamic_cast *>(&t_func); @@ -698,7 +683,7 @@ namespace chaiscript } } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &) const override + bool call_match(const std::vector &vals, const Type_Conversions_State &) const override { if (vals.size() != 1) { @@ -708,13 +693,13 @@ namespace chaiscript return vals[0].get_type_info().bare_equal(user_type()); } - virtual std::string annotation() const override + std::string annotation() const override { return ""; } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { const Boxed_Value &bv = params[0]; if (bv.is_const()) @@ -762,7 +747,7 @@ namespace chaiscript dispatch_error(const dispatch_error &) = default; - virtual ~dispatch_error() noexcept {} + virtual ~dispatch_error() noexcept = default; std::vector parameters; std::vector functions; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 7c4c77c..efbcc99 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -82,20 +82,18 @@ namespace chaiscript } struct Binary_Operator_AST_Node : AST_Node { - public: Binary_Operator_AST_Node(const std::string &t_oper, Parse_Location t_loc, std::vector t_children) : AST_Node(t_oper, AST_Node_Type::Binary, std::move(t_loc), std::move(t_children)), m_oper(Operators::to_operator(t_oper)) - { } + { } - virtual ~Binary_Operator_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { auto lhs = this->children[0]->eval(t_ss); auto rhs = this->children[1]->eval(t_ss); return do_oper(t_ss, m_oper, text, lhs, rhs); } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")"; } @@ -131,28 +129,25 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Int_AST_Node : public AST_Node { - public: + struct Int_AST_Node final : AST_Node { Int_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, std::move(t_loc)), m_value(std::move(t_bv)) { assert(text != ""); } - virtual ~Int_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override { return m_value; } private: Boxed_Value m_value; - }; - struct Float_AST_Node : public AST_Node { - public: + struct Float_AST_Node final : AST_Node { Float_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, Boxed_Value t_bv) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Float, std::move(t_loc)), m_value(std::move(t_bv)) { } - virtual ~Float_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override { return m_value; } @@ -161,15 +156,13 @@ namespace chaiscript }; - struct Id_AST_Node : public AST_Node { - public: + struct Id_AST_Node final : AST_Node { Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), m_value(get_value(t_ast_node_text)), m_loc(0) - { } + { } - virtual ~Id_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (!m_value.is_undef()) { return m_value; @@ -206,39 +199,33 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Char_AST_Node : public AST_Node { - public: + struct Char_AST_Node final : AST_Node { Char_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Char, std::move(t_loc)) { } - virtual ~Char_AST_Node() {} }; - struct Str_AST_Node : public AST_Node { - public: + struct Str_AST_Node final : AST_Node { Str_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Str, std::move(t_loc)) { } - virtual ~Str_AST_Node() {} }; - struct Eol_AST_Node : public AST_Node { - public: + struct Eol_AST_Node final : AST_Node { Eol_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Eol, std::move(t_loc)) { } - virtual ~Eol_AST_Node() {} - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "\n"; } }; - struct Fun_Call_AST_Node : public AST_Node { - public: + struct Fun_Call_AST_Node final : AST_Node { Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } - virtual ~Fun_Call_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override + { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params; @@ -278,7 +265,7 @@ namespace chaiscript } } - virtual std::string pretty_print() const override + std::string pretty_print() const override { std::ostringstream oss; @@ -302,13 +289,11 @@ namespace chaiscript - struct Arg_AST_Node : public AST_Node { - public: + struct Arg_AST_Node final : AST_Node { Arg_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } - virtual ~Arg_AST_Node() {} - virtual std::string pretty_print() const override + std::string pretty_print() const override { std::ostringstream oss; for (size_t j = 0; j < this->children.size(); ++j) { @@ -324,13 +309,11 @@ namespace chaiscript } }; - struct Arg_List_AST_Node : public AST_Node { - public: + struct Arg_List_AST_Node final : AST_Node { Arg_List_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } - virtual ~Arg_List_AST_Node() {} - virtual std::string pretty_print() const override + std::string pretty_print() const override { std::ostringstream oss; for (size_t j = 0; j < this->children.size(); ++j) { @@ -371,9 +354,9 @@ namespace chaiscript { if (t_node->children.size() < 2) { - return std::pair(); + return {}; } else { - return std::pair(t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)); + return {t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)}; } } @@ -389,19 +372,14 @@ namespace chaiscript } }; - struct Equation_AST_Node : public AST_Node { - public: + struct Equation_AST_Node final : AST_Node { Equation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, std::move(t_loc), std::move(t_children)), m_oper(Operators::to_operator(children[1]->text)) { assert(children.size() == 3); } - Operators::Opers m_oper; - mutable std::atomic_uint_fast32_t m_loc; - mutable std::atomic_uint_fast32_t m_clone_loc; - virtual ~Equation_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); Boxed_Value rhs = this->children[2]->eval(t_ss); Boxed_Value lhs = this->children[0]->eval(t_ss); @@ -469,17 +447,20 @@ namespace chaiscript return rhs; } + + private: + Operators::Opers m_oper; + mutable std::atomic_uint_fast32_t m_loc; + mutable std::atomic_uint_fast32_t m_clone_loc; }; - struct Global_Decl_AST_Node : public AST_Node { - public: + struct Global_Decl_AST_Node final : AST_Node { Global_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Global_Decl, std::move(t_loc), std::move(t_children)) { } - virtual ~Global_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const std::string &idname = - [&]()->const std::string &{ + [&]()->const std::string & { if (children[0]->identifier == AST_Node_Type::Reference) { return children[0]->children[0]->text; } else { @@ -498,12 +479,11 @@ namespace chaiscript }; - struct Var_Decl_AST_Node : public AST_Node { - public: + struct Var_Decl_AST_Node final : AST_Node { Var_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, std::move(t_loc), std::move(t_children)) { } - virtual ~Var_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (this->children[0]->identifier == AST_Node_Type::Reference) { return this->children[0]->eval(t_ss); @@ -524,7 +504,7 @@ namespace chaiscript } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "var " + this->children[0]->text; } @@ -532,15 +512,14 @@ namespace chaiscript }; - struct Array_Call_AST_Node : public AST_Node { - public: + struct Array_Call_AST_Node final : AST_Node { Array_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Array_Call, std::move(t_loc), std::move(t_children)) { } - virtual ~Array_Call_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - std::vector params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; + const std::vector params{children[0]->eval(t_ss), children[1]->eval(t_ss)}; try { fpp.save_params(params); @@ -549,10 +528,9 @@ namespace chaiscript catch(const exception::dispatch_error &e){ throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss ); } - } - virtual std::string pretty_print() const override + std::string pretty_print() const override { std::ostringstream oss; oss << this->children[0]->pretty_print(); @@ -567,19 +545,18 @@ namespace chaiscript return oss.str(); } + private: mutable std::atomic_uint_fast32_t m_loc; }; - struct Dot_Access_AST_Node : public AST_Node { - public: + struct Dot_Access_AST_Node final : AST_Node { Dot_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Dot_Access, std::move(t_loc), std::move(t_children)), m_fun_name( ((children[2]->identifier == AST_Node_Type::Fun_Call) || (children[2]->identifier == AST_Node_Type::Array_Call))? children[2]->children[0]->text:children[2]->text) { } - virtual ~Dot_Access_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); @@ -626,42 +603,37 @@ namespace chaiscript private: mutable std::atomic_uint_fast32_t m_loc; mutable std::atomic_uint_fast32_t m_array_loc; - std::string m_fun_name; + const std::string m_fun_name; }; - struct Quoted_String_AST_Node : public AST_Node { - public: + struct Quoted_String_AST_Node final : AST_Node { Quoted_String_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Quoted_String, std::move(t_loc)), m_value(const_var(text)) { } - virtual ~Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override { + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override { return m_value; } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "\"" + text + "\""; } private: Boxed_Value m_value; - }; - struct Single_Quoted_String_AST_Node : public AST_Node { - public: + struct Single_Quoted_String_AST_Node final : AST_Node { Single_Quoted_String_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Single_Quoted_String, std::move(t_loc)), m_value(const_var(char(text.at(0)))) { } - virtual ~Single_Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ return m_value; } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "'" + text + "'"; } @@ -670,15 +642,12 @@ namespace chaiscript Boxed_Value m_value; }; - struct Lambda_AST_Node : public AST_Node { - public: + struct Lambda_AST_Node final : AST_Node { Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), m_param_names(Arg_List_AST_Node::get_arg_names(children[1])) { } - virtual ~Lambda_AST_Node() {} - - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const auto captures = [&]()->std::map{ std::map named_captures; @@ -689,7 +658,6 @@ namespace chaiscript }(); const auto numparams = this->children[1]->children.size(); - const auto param_names = m_param_names; const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); const auto &lambda_node = this->children.back(); @@ -697,7 +665,7 @@ namespace chaiscript return Boxed_Value( dispatch::make_dynamic_proxy_function( - [engine, lambda_node, param_names, captures](const std::vector &t_params) + [engine, lambda_node, param_names = this->m_param_names, captures](const std::vector &t_params) { return detail::eval_function(engine, lambda_node, param_names, t_params, &captures); }, @@ -707,17 +675,15 @@ namespace chaiscript } private: - std::vector m_param_names; + const std::vector m_param_names; }; - struct Block_AST_Node : public AST_Node { - public: + struct Block_AST_Node final : AST_Node { Block_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Block, std::move(t_loc), std::move(t_children)) { } - virtual ~Block_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); const auto num_children = children.size(); @@ -725,17 +691,14 @@ namespace chaiscript children[i]->eval(t_ss); } return children.back()->eval(t_ss); - } }; - struct Def_AST_Node : public AST_Node { - public: + struct Def_AST_Node final : AST_Node { Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } - virtual ~Def_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ std::vector t_param_names; size_t numparams = 0; AST_NodePtr guardnode; @@ -794,12 +757,11 @@ namespace chaiscript }; - struct While_AST_Node : public AST_Node { - public: + struct While_AST_Node final : AST_Node { While_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::While, std::move(t_loc), std::move(t_children)) { } - virtual ~While_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -820,12 +782,11 @@ namespace chaiscript } }; - struct Class_AST_Node : public AST_Node { - public: + struct Class_AST_Node final : AST_Node { Class_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Class, std::move(t_loc), std::move(t_children)) { } - virtual ~Class_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); /// \todo do this better @@ -838,29 +799,26 @@ namespace chaiscript } }; - struct Ternary_Cond_AST_Node : public AST_Node { - public: + struct Ternary_Cond_AST_Node final : AST_Node { Ternary_Cond_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } - virtual ~Ternary_Cond_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (get_bool_condition(children[0]->eval(t_ss))) { return children[1]->eval(t_ss); - } - else { + } else { return children[2]->eval(t_ss); } } }; - struct If_AST_Node : public AST_Node { - public: + struct If_AST_Node final : AST_Node { If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::If, std::move(t_loc), std::move(t_children)) { } - virtual ~If_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { if (get_bool_condition(children[0]->eval(t_ss))) { return children[1]->eval(t_ss); @@ -886,14 +844,12 @@ namespace chaiscript }; - struct For_AST_Node : public AST_Node { - public: + struct For_AST_Node final : AST_Node { For_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::For, std::move(t_loc), std::move(t_children)) { assert(children.size() == 4); } - virtual ~For_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -920,12 +876,11 @@ namespace chaiscript }; - struct Switch_AST_Node : public AST_Node { - public: + struct Switch_AST_Node final : AST_Node { Switch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, std::move(t_loc), std::move(t_children)) { } - virtual ~Switch_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { bool breaking = false; size_t currentCase = 1; bool hasMatched = false; @@ -964,14 +919,12 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Case_AST_Node : public AST_Node { - public: + struct Case_AST_Node final : AST_Node { Case_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Case, std::move(t_loc), std::move(t_children)) { assert(children.size() == 2); /* how many children does it have? */ } - virtual ~Case_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); children[1]->eval(t_ss); @@ -980,13 +933,12 @@ namespace chaiscript } }; - struct Default_AST_Node : public AST_Node { - public: + struct Default_AST_Node final : AST_Node { Default_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Default, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } - virtual ~Default_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); children[0]->eval(t_ss); @@ -996,12 +948,11 @@ namespace chaiscript }; - struct Inline_Array_AST_Node : public AST_Node { - public: + struct Inline_Array_AST_Node final : AST_Node { Inline_Array_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, std::move(t_loc), std::move(t_children)) { } - virtual ~Inline_Array_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { std::vector vec; if (!children.empty()) { @@ -1022,20 +973,20 @@ namespace chaiscript } } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "[" + AST_Node::pretty_print() + "]"; } + private: mutable std::atomic_uint_fast32_t m_loc; }; - struct Inline_Map_AST_Node : public AST_Node { - public: + struct Inline_Map_AST_Node final : AST_Node { Inline_Map_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, std::move(t_loc), std::move(t_children)) { } - virtual ~Inline_Map_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { std::map retval; @@ -1055,15 +1006,15 @@ namespace chaiscript } } + private: mutable std::atomic_uint_fast32_t m_loc; }; - struct Return_AST_Node : public AST_Node { - public: + struct Return_AST_Node final : AST_Node { Return_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Return, std::move(t_loc), std::move(t_children)) { } - virtual ~Return_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ if (!this->children.empty()) { throw detail::Return_Value(children[0]->eval(t_ss)); } @@ -1071,15 +1022,13 @@ namespace chaiscript throw detail::Return_Value(Boxed_Value()); } } - }; - struct File_AST_Node : public AST_Node { - public: + struct File_AST_Node final : AST_Node { File_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, std::move(t_loc), std::move(t_children)) { } - virtual ~File_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { try { const auto num_children = children.size(); @@ -1099,13 +1048,12 @@ namespace chaiscript } }; - struct Reference_AST_Node : public AST_Node { - public: + struct Reference_AST_Node final : AST_Node { Reference_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Reference, std::move(t_loc), std::move(t_children)) { assert(children.size() == 1); } - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { Boxed_Value bv; t_ss.add_object(this->children[0]->text, bv); @@ -1115,19 +1063,15 @@ namespace chaiscript throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'"); } } - - virtual ~Reference_AST_Node() {} }; - struct Prefix_AST_Node : public AST_Node { - public: + struct Prefix_AST_Node final : AST_Node { Prefix_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, std::move(t_loc), std::move(t_children)), m_oper(Operators::to_operator(children[0]->text, true)) { } - virtual ~Prefix_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ Boxed_Value bv(children[1]->eval(t_ss)); try { @@ -1150,63 +1094,51 @@ namespace chaiscript mutable std::atomic_uint_fast32_t m_loc; }; - struct Break_AST_Node : public AST_Node { - public: + struct Break_AST_Node final : AST_Node { Break_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Break, std::move(t_loc), std::move(t_children)) { } - virtual ~Break_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Break_Loop(); } }; - struct Continue_AST_Node : public AST_Node { - public: + struct Continue_AST_Node final : AST_Node { Continue_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Continue, std::move(t_loc), std::move(t_children)) { } - virtual ~Continue_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ throw detail::Continue_Loop(); } }; - struct Noop_AST_Node : public AST_Node { - public: + struct Noop_AST_Node final : public AST_Node { Noop_AST_Node() : - AST_Node("", AST_Node_Type::Noop, Parse_Location()), - m_value(const_var(true)) + AST_Node("", AST_Node_Type::Noop, Parse_Location()) { } - virtual ~Noop_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &) const override{ // It's a no-op, that evaluates to "true" - return m_value; + // the magic-static version of const_var(true) helps us here + return const_var(true); } - - private: - Boxed_Value m_value; }; - struct Map_Pair_AST_Node : public AST_Node { - public: + struct Map_Pair_AST_Node final : AST_Node { Map_Pair_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Map_Pair, std::move(t_loc), std::move(t_children)) { } - virtual ~Map_Pair_AST_Node() {} }; - struct Value_Range_AST_Node : public AST_Node { - public: + struct Value_Range_AST_Node final : AST_Node { Value_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Value_Range, std::move(t_loc), std::move(t_children)) { } - virtual ~Value_Range_AST_Node() {} }; - struct Inline_Range_AST_Node : public AST_Node { - public: + struct Inline_Range_AST_Node final : AST_Node { Inline_Range_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Range, std::move(t_loc), std::move(t_children)) { } - virtual ~Inline_Range_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { auto oper1 = children[0]->children[0]->children[0]->eval(t_ss); auto oper2 = children[0]->children[0]->children[1]->eval(t_ss); @@ -1217,21 +1149,18 @@ namespace chaiscript } } + private: mutable std::atomic_uint_fast32_t m_loc; }; - struct Annotation_AST_Node : public AST_Node { - public: + struct Annotation_AST_Node final : AST_Node { Annotation_AST_Node(std::string t_ast_node_text, Parse_Location t_loc) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Annotation, std::move(t_loc)) { } - virtual ~Annotation_AST_Node() {} }; - struct Try_AST_Node : public AST_Node { - public: + struct Try_AST_Node final : AST_Node { Try_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Try, std::move(t_loc), std::move(t_children)) { } - virtual ~Try_AST_Node() {} Boxed_Value handle_exception(const chaiscript::detail::Dispatch_State &t_ss, const Boxed_Value &t_except) const { @@ -1294,7 +1223,7 @@ namespace chaiscript return retval; } - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { Boxed_Value retval; chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1338,26 +1267,21 @@ namespace chaiscript }; - struct Catch_AST_Node : public AST_Node { - public: + struct Catch_AST_Node final : AST_Node { Catch_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Catch, std::move(t_loc), std::move(t_children)) { } - virtual ~Catch_AST_Node() {} }; - struct Finally_AST_Node : public AST_Node { - public: + struct Finally_AST_Node final : AST_Node { Finally_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Finally, std::move(t_loc), std::move(t_children)) { } - virtual ~Finally_AST_Node() {} }; - struct Method_AST_Node : public AST_Node { - public: + struct Method_AST_Node final : AST_Node { Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } - virtual ~Method_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ AST_NodePtr guardnode; @@ -1443,12 +1367,11 @@ namespace chaiscript }; - struct Attr_Decl_AST_Node : public AST_Node { - public: + struct Attr_Decl_AST_Node final : AST_Node { Attr_Decl_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Attr_Decl, std::move(t_loc), std::move(t_children)) { } - virtual ~Attr_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { const auto &d = t_ss->get_parent_locals(); const auto itr = d.find("_current_class_name"); @@ -1480,36 +1403,35 @@ namespace chaiscript }; - struct Logical_And_AST_Node : public AST_Node { - public: + struct Logical_And_AST_Node final : AST_Node { Logical_And_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_And, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } - virtual ~Logical_And_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override + { return const_var(get_bool_condition(children[0]->eval(t_ss)) && get_bool_condition(children[2]->eval(t_ss))); } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "(" + AST_Node::pretty_print() + ")"; } }; - struct Logical_Or_AST_Node : public AST_Node { - public: + struct Logical_Or_AST_Node final : AST_Node { Logical_Or_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector t_children) : AST_Node(std::move(t_ast_node_text), AST_Node_Type::Logical_Or, std::move(t_loc), std::move(t_children)) { assert(children.size() == 3); } - virtual ~Logical_Or_AST_Node() {} - virtual Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ + + Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override + { return const_var(get_bool_condition(children[0]->eval(t_ss)) || get_bool_condition(children[2]->eval(t_ss))); } - virtual std::string pretty_print() const override + std::string pretty_print() const override { return "(" + AST_Node::pretty_print() + ")"; } @@ -1520,3 +1442,4 @@ namespace chaiscript } #endif /* CHAISCRIPT_EVAL_HPP_ */ + From 5247de7d1b87c5f3b539d23cfee8f69f26b852f9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 10:21:39 -0700 Subject: [PATCH 30/33] use a global void value for returning unknown values --- .../chaiscript/dispatchkit/boxed_value.hpp | 5 ++++ .../chaiscript/dispatchkit/handle_return.hpp | 2 +- .../chaiscript/language/chaiscript_eval.hpp | 24 +++++++++---------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 70bfe12..7388c13 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -411,6 +411,11 @@ namespace chaiscript return detail::const_var_impl(t); } + inline Boxed_Value void_var() { + static const auto v = Boxed_Value(Boxed_Value::Void_Type()); + return v; + } + inline Boxed_Value const_var(bool b) { static const auto t = detail::const_var_impl(true); static const auto f = detail::const_var_impl(false); diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 2650e3b..17c6d4e 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -268,7 +268,7 @@ namespace chaiscript { static Boxed_Value handle() { - return Boxed_Value(Boxed_Value::Void_Type()); + return void_var(); } }; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index efbcc99..d7bc7e0 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -752,7 +752,7 @@ namespace chaiscript } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Function redefined '" + e.name() + "'"); } - return Boxed_Value(); + return void_var(); } }; @@ -778,7 +778,7 @@ namespace chaiscript // loop was broken intentionally } - return Boxed_Value(); + return void_var(); } }; @@ -795,7 +795,7 @@ namespace chaiscript children[1]->eval(t_ss); - return Boxed_Value(); + return void_var(); } }; @@ -839,7 +839,7 @@ namespace chaiscript } } - return Boxed_Value(); + return void_var(); } }; @@ -871,7 +871,7 @@ namespace chaiscript // loop broken } - return Boxed_Value(); + return void_var(); } }; @@ -913,7 +913,7 @@ namespace chaiscript } ++currentCase; } - return Boxed_Value(); + return void_var(); } mutable std::atomic_uint_fast32_t m_loc; @@ -929,7 +929,7 @@ namespace chaiscript children[1]->eval(t_ss); - return Boxed_Value(); + return void_var(); } }; @@ -943,7 +943,7 @@ namespace chaiscript children[0]->eval(t_ss); - return Boxed_Value(); + return void_var(); } }; @@ -1019,7 +1019,7 @@ namespace chaiscript throw detail::Return_Value(children[0]->eval(t_ss)); } else { - throw detail::Return_Value(Boxed_Value()); + throw detail::Return_Value(void_var()); } } }; @@ -1038,7 +1038,7 @@ namespace chaiscript } return children.back()->eval(t_ss); } else { - return Boxed_Value(); + return void_var(); } } catch (const detail::Continue_Loop &) { throw exception::eval_error("Unexpected `continue` statement outside of a loop"); @@ -1362,7 +1362,7 @@ namespace chaiscript } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Method redefined '" + e.name() + "'"); } - return Boxed_Value(); + return void_var(); } }; @@ -1397,7 +1397,7 @@ namespace chaiscript } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Attribute redefined '" + e.name() + "'"); } - return Boxed_Value(); + return void_var(); } }; From 9a5ef38d4a3503b78d95c912a66016ba1d7b74fc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 10:57:20 -0700 Subject: [PATCH 31/33] Simplify exception_specification types * move to variadic * delete lots of implementation details --- .../dispatchkit/exception_specification.hpp | 100 ++---------------- 1 file changed, 7 insertions(+), 93 deletions(-) diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 1b4384b..0c9b40f 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -23,12 +23,11 @@ namespace chaiscript { namespace detail { - /// \todo make this a variadic template struct Exception_Handler_Base { virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0; - virtual ~Exception_Handler_Base() {} + virtual ~Exception_Handler_Base() = default; protected: template @@ -38,65 +37,12 @@ namespace chaiscript } }; - template - struct Exception_Handler_Impl1 : Exception_Handler_Base + template + struct Exception_Handler_Impl : Exception_Handler_Base { - virtual ~Exception_Handler_Impl1() {} - - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override + void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { - throw_type(bv, t_engine); - } - }; - template - struct Exception_Handler_Impl2 : Exception_Handler_Base - { - virtual ~Exception_Handler_Impl2() {} - - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override - { - throw_type(bv, t_engine); - throw_type(bv, t_engine); - } - }; - - template - struct Exception_Handler_Impl3 : Exception_Handler_Base - { - virtual ~Exception_Handler_Impl3() {} - - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override - { - throw_type(bv, t_engine); - throw_type(bv, t_engine); - throw_type(bv, t_engine); - } - }; - template - struct Exception_Handler_Impl4 : Exception_Handler_Base - { - virtual ~Exception_Handler_Impl4() {} - - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override - { - throw_type(bv, t_engine); - throw_type(bv, t_engine); - throw_type(bv, t_engine); - throw_type(bv, t_engine); - } - }; - template - struct Exception_Handler_Impl5 : Exception_Handler_Base - { - virtual ~Exception_Handler_Impl5() {} - - virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override - { - throw_type(bv, t_engine); - throw_type(bv, t_engine); - throw_type(bv, t_engine); - throw_type(bv, t_engine); - throw_type(bv, t_engine); + (void)std::initializer_list{(throw_type(bv, t_engine), 0)...}; } }; } @@ -155,42 +101,10 @@ namespace chaiscript /// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing /// \sa \ref exceptions - template + template Exception_Handler exception_specification() { - return Exception_Handler(new detail::Exception_Handler_Impl1()); - } - - /// \brief creates a chaiscript::Exception_Handler which handles two types of exception unboxing - /// \sa \ref exceptions - template - Exception_Handler exception_specification() - { - return Exception_Handler(new detail::Exception_Handler_Impl2()); - } - - /// \brief creates a chaiscript::Exception_Handler which handles three types of exception unboxing - /// \sa \ref exceptions - template - Exception_Handler exception_specification() - { - return Exception_Handler(new detail::Exception_Handler_Impl3()); - } - - /// \brief creates a chaiscript::Exception_Handler which handles four types of exception unboxing - /// \sa \ref exceptions - template - Exception_Handler exception_specification() - { - return Exception_Handler(new detail::Exception_Handler_Impl4()); - } - - /// \brief creates a chaiscript::Exception_Handler which handles five types of exception unboxing - /// \sa \ref exceptions - template - Exception_Handler exception_specification() - { - return Exception_Handler(new detail::Exception_Handler_Impl5()); + return std::make_shared>(); } } From a3365a9c4af155ae786bd762684d791460a4a477 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 13:45:01 -0700 Subject: [PATCH 32/33] Enable use of shared_mutex now on C++14 --- include/chaiscript/chaiscript_threading.hpp | 23 ++++++--------------- include/chaiscript/dispatchkit/any.hpp | 17 ++++++--------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 2a0e63c..126edb9 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -13,6 +13,7 @@ #ifndef CHAISCRIPT_NO_THREADS #include #include +#include #else #ifndef CHAISCRIPT_NO_THREADS_WARNING #pragma message ("ChaiScript is compiling without thread safety.") @@ -42,28 +43,16 @@ namespace chaiscript #ifndef CHAISCRIPT_NO_THREADS template - class unique_lock : public std::unique_lock - { - public: - explicit unique_lock(T &t) : std::unique_lock(t) {} - }; + using unique_lock = std::unique_lock; template - class shared_lock : public std::unique_lock - { - public: - explicit shared_lock(T &t) : std::unique_lock(t) {} - void unlock() {} - }; + using shared_lock = std::shared_lock; template - class lock_guard : public std::lock_guard - { - public: - explicit lock_guard(T &t) : std::lock_guard(t) {} - }; + using lock_guard = std::lock_guard; - class shared_mutex : public std::mutex { }; + + using shared_mutex = std::shared_timed_mutex; using std::mutex; diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index c9b62a1..e492031 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -28,10 +28,10 @@ namespace chaiscript { bad_any_cast(const bad_any_cast &) = default; - virtual ~bad_any_cast() noexcept {} + ~bad_any_cast() noexcept override = default; /// \brief Description of what error occurred - virtual const char * what() const noexcept override + const char * what() const noexcept override { return m_what.c_str(); } @@ -53,9 +53,10 @@ namespace chaiscript { Data &operator=(const Data &) = delete; - virtual ~Data() {} + virtual ~Data() = default; virtual void *data() = 0; + const std::type_info &type() const { return m_type; @@ -74,8 +75,6 @@ namespace chaiscript { { } - virtual ~Data_Impl() {} - virtual void *data() override { return &m_data; @@ -96,6 +95,8 @@ namespace chaiscript { public: // construct/copy/destruct Any() = default; + Any(Any &&) = default; + Any &operator=(Any &&t_any) = default; Any(const Any &t_any) { @@ -107,8 +108,6 @@ namespace chaiscript { } } - Any(Any &&) = default; - Any &operator=(Any &&t_any) = default; template::type>::value>::type> @@ -137,10 +136,6 @@ namespace chaiscript { } - ~Any() - { - } - // modifiers Any & swap(Any &t_other) { From a363ef5e0ebebcecb6ce05a049a694db94bd3d25 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 11 Mar 2016 14:45:40 -0700 Subject: [PATCH 33/33] C++11/14 updates --- .../chaiscript/dispatchkit/bad_boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/boxed_cast.hpp | 6 +-- .../chaiscript/dispatchkit/boxed_number.hpp | 2 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 54 +++++++++---------- .../chaiscript/dispatchkit/dynamic_object.hpp | 2 +- .../dispatchkit/dynamic_object_detail.hpp | 25 ++++----- 6 files changed, 39 insertions(+), 52 deletions(-) diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index 44cbf25..ee2be60 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -46,7 +46,7 @@ namespace chaiscript } bad_boxed_cast(const bad_boxed_cast &) = default; - virtual ~bad_boxed_cast() noexcept {} + virtual ~bad_boxed_cast() noexcept = default; /// \brief Description of what error occurred virtual const char * what() const noexcept override diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 44450a0..5a11ee9 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -82,21 +82,19 @@ namespace chaiscript if (t_conversions && (*t_conversions)->convertable_type()) { try { - // std::cout << "trying an up conversion " << typeid(Type).name() << '\n'; // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // either way, we are not responsible if it doesn't work return detail::Cast_Helper::cast((*t_conversions)->boxed_type_conversion(t_conversions->saves(), bv), t_conversions); } catch (...) { try { - // std::cout << "trying a down conversion " << typeid(Type).name() << '\n'; - // try going the other way - down the inheritance graph + // try going the other way return detail::Cast_Helper::cast((*t_conversions)->boxed_type_down_conversion(t_conversions->saves(), bv), t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } } } else { - // If it's not polymorphic, just throw the error, don't waste the time on the + // If it's not convertable, just throw the error, don't waste the time on the // attempted dynamic_cast throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 011b6fa..7eefe99 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -30,7 +30,7 @@ namespace chaiscript { arithmetic_error(const std::string& reason) : std::runtime_error("Arithmetic error: " + reason) {} arithmetic_error(const arithmetic_error &) = default; - virtual ~arithmetic_error() noexcept {} + virtual ~arithmetic_error() noexcept = default; }; } } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index d98400b..1345b13 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -56,14 +56,14 @@ namespace chaiscript class reserved_word_error : public std::runtime_error { public: - reserved_word_error(const std::string &t_word) noexcept + explicit reserved_word_error(const std::string &t_word) noexcept : std::runtime_error("Reserved word not allowed in object name: " + t_word), m_word(t_word) { } reserved_word_error(const reserved_word_error &) = default; - virtual ~reserved_word_error() noexcept {} + virtual ~reserved_word_error() noexcept = default; std::string word() const { @@ -78,14 +78,14 @@ namespace chaiscript class illegal_name_error : public std::runtime_error { public: - illegal_name_error(const std::string &t_name) noexcept + explicit illegal_name_error(const std::string &t_name) noexcept : std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name) { } illegal_name_error(const illegal_name_error &) = default; - virtual ~illegal_name_error() noexcept {} + virtual ~illegal_name_error() noexcept = default; std::string name() const { @@ -101,14 +101,14 @@ namespace chaiscript class name_conflict_error : public std::runtime_error { public: - name_conflict_error(const std::string &t_name) noexcept + explicit name_conflict_error(const std::string &t_name) noexcept : std::runtime_error("Name already exists in current context " + t_name), m_name(t_name) { } name_conflict_error(const name_conflict_error &) = default; - virtual ~name_conflict_error() noexcept {} + virtual ~name_conflict_error() noexcept = default; std::string name() const { @@ -131,7 +131,7 @@ namespace chaiscript } global_non_const(const global_non_const &) = default; - virtual ~global_non_const() noexcept {} + virtual ~global_non_const() noexcept = default; }; } @@ -194,30 +194,28 @@ namespace chaiscript apply_globals(m_globals.begin(), m_globals.end(), t_engine); } - ~Module() - { - } - bool has_function(const Proxy_Function &new_f, const std::string &name) { - return std::any_of(m_funcs.begin(), m_funcs.end(), [&](const std::pair &existing_f) { - return existing_f.second == name && *(existing_f.first) == *(new_f); - }); + return std::any_of(m_funcs.begin(), m_funcs.end(), + [&](const std::pair &existing_f) { + return existing_f.second == name && *(existing_f.first) == *(new_f); + } + ); } private: - std::vector > m_typeinfos; - std::vector > m_funcs; - std::vector > m_globals; + std::vector> m_typeinfos; + std::vector> m_funcs; + std::vector> m_globals; std::vector m_evals; std::vector m_conversions; template static void apply(InItr begin, const InItr end, T &t) { - for_each(begin, end, [&t](typename std::iterator_traits::reference obj) - { + for_each(begin, end, + [&t](const auto &obj) { try { t.add(obj.first, obj.second); } catch (const chaiscript::exception::name_conflict_error &) { @@ -600,12 +598,10 @@ namespace chaiscript { t_holder.call_params.pop_back(); StackData &stack = get_stack_data(t_holder); - if (stack.size() > 1) - { - stack.pop_back(); - } else { - throw std::range_error("Unable to pop global stack"); - } + + assert(!stack.empty()); + + stack.pop_back(); } @@ -916,10 +912,8 @@ namespace chaiscript } for (const auto &fun : t_funs) { - if (fun->is_attribute_function()) { - if (fun->compare_first_type(t_params[0], t_conversions)) { - return true; - } + if (fun->is_attribute_function() + && fun->compare_first_type(t_params[0], t_conversions)) { } } @@ -1107,7 +1101,7 @@ namespace chaiscript const Const_Proxy_Function &f = this->boxed_cast(params[0]); const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves()); - return Boxed_Value(f->call_match(std::vector(params.begin() + 1, params.end()), convs)); + return const_var(f->call_match(std::vector(params.begin() + 1, params.end()), convs)); } /// Dump all system info to stdout diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index d6052d9..b35ded6 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -33,7 +33,7 @@ namespace chaiscript option_explicit_set(const option_explicit_set &) = default; - virtual ~option_explicit_set() noexcept {} + virtual ~option_explicit_set() noexcept = default; }; class Dynamic_Object diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index 28df3e9..14f080d 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -39,7 +39,7 @@ namespace chaiscript /// A Proxy_Function implementation designed for calling a function /// that is automatically guarded based on the first param based on the /// param's type name - class Dynamic_Object_Function : public Proxy_Function_Base + class Dynamic_Object_Function final : public Proxy_Function_Base { public: Dynamic_Object_Function( @@ -67,12 +67,11 @@ namespace chaiscript && "Programming error, Dynamic_Object_Function must have at least one parameter (this)"); } - virtual ~Dynamic_Object_Function() {} Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete; Dynamic_Object_Function(Dynamic_Object_Function &) = delete; - virtual bool operator==(const Proxy_Function_Base &f) const override + bool operator==(const Proxy_Function_Base &f) const override { if (const auto *df = dynamic_cast(&f)) { @@ -82,9 +81,9 @@ namespace chaiscript } } - virtual bool is_attribute_function() const override { return m_is_attribute; } + bool is_attribute_function() const override { return m_is_attribute; } - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) { @@ -94,12 +93,12 @@ namespace chaiscript } } - virtual std::vector get_contained_functions() const override + std::vector get_contained_functions() const override { return {m_func}; } - virtual std::string annotation() const override + std::string annotation() const override { return m_func->annotation(); } @@ -170,9 +169,7 @@ namespace chaiscript Proxy_Function m_func; std::unique_ptr m_ti; const Type_Info m_doti; - bool m_is_attribute; - - + const bool m_is_attribute; }; @@ -182,7 +179,7 @@ namespace chaiscript * that is automatically guarded based on the first param based on the * param's type name */ - class Dynamic_Object_Constructor : public Proxy_Function_Base + class Dynamic_Object_Constructor final : public Proxy_Function_Base { public: Dynamic_Object_Constructor( @@ -208,9 +205,7 @@ namespace chaiscript return std::vector(begin, end); } - virtual ~Dynamic_Object_Constructor() {} - - virtual bool operator==(const Proxy_Function_Base &f) const override + bool operator==(const Proxy_Function_Base &f) const override { const Dynamic_Object_Constructor *dc = dynamic_cast(&f); return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); @@ -230,7 +225,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { auto bv = Boxed_Value(Dynamic_Object(m_type_name), true); std::vector new_params{bv};