diff --git a/.travis.yml b/.travis.yml index 210e29e..458ccd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,21 +2,33 @@ language: cpp compiler: - gcc env: - - GCC_VER=4.6 - - GCC_VER=4.8 + matrix: + - GCC_VER="4.6" + - GCC_VER="4.8" + + global: + - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= + # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created + - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" + 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 - sudo pip install cpp-coveralls - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - - sudo apt-get install -qq g++-4.8 - - if [ "$GCC_VER" = "4.8" ]; then export CXX="g++-4.8" CC="gcc-4.8" GCOV="gcov-4.8"; else export CXX="g++-4.6" CC="gcc-4.6" GCOV="gcov-4.6"; fi + - sudo apt-get install -qq g++-$GCC_VER + script: - - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - - make -j2 + - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . ; fi + - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - make test - - coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV + - if [ ${COVERAGE} = 1 ]; then coveralls -e "unittests/catch.hpp" -E ".*\.cpp" --gcov $GCOV --gcov-options '\-lp' ; fi + after_script: - - contrib/codeanalysis/runcppcheck.sh + - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi + + notifications: email: recipients: @@ -29,8 +41,15 @@ notifications: on_success: change # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always on_start: false # default: false -env: - global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= + +addons: + coverity_scan: + project: + name: "ChaiScript/ChaiScript" + description: "Build submitted via Travis CI" + notification_email: jason@emptycrate.com + build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . " + build_command: "cmake --build . -- -j2" + branch_pattern: coverity_scan diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 8e45977..6d0fd99 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -35,6 +35,10 @@ #define CHAISCRIPT_HAS_THREAD_LOCAL #endif +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#define CHAISCRIPT_GCC_4_6 +#endif + #if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__) #define CHAISCRIPT_OVERRIDE override #else diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 5e7d18d..02822b1 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1175,8 +1175,13 @@ namespace chaiscript const auto lhssize = lhsparamtypes.size(); const auto rhssize = rhsparamtypes.size(); - CHAISCRIPT_CONSTEXPR auto boxed_type = user_type(); - CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type(); +#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 for (size_t i = 1; i < lhssize && i < rhssize; ++i) { diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 25ff980..d8a10cc 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -54,6 +54,113 @@ namespace chaiscript { namespace detail { + /** + * Used by Proxy_Function_Impl to return a list of all param types + * it contains. + */ + template + std::vector build_param_type_list(Ret (*)(Params...)) + { + /// \note somehow this is responsible for a large part of the code generation + return { user_type(), user_type()... }; + } + + +#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 &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 &) + { + } + }; + + + /** + * 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 &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 std::function &f, + const std::vector ¶ms, const Type_Conversions &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 std::function &f, + const std::vector &, const Type_Conversions &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 std::function &f, + const std::vector ¶ms, const Type_Conversions &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 { @@ -71,16 +178,6 @@ namespace chaiscript typedef Indexes indexes; }; - /** - * Used by Proxy_Function_Impl to return a list of all param types - * it contains. - */ - template - std::vector build_param_type_list(Ret (*)(Params...)) - { - /// \note somehow this is responsible for a large part of the code generation - return { user_type(), user_type()... }; - } /** @@ -132,6 +229,8 @@ namespace chaiscript return call_func(sig, indexes(), f, params, t_conversions); } +#endif + } } diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index de61ab6..1db31be 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, + 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_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), @@ -38,7 +38,7 @@ namespace chaiscript { } - CHAISCRIPT_CONSTEXPR Type_Info() + Type_Info() : m_type_info(nullptr), m_bare_type_info(nullptr), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), @@ -55,40 +55,40 @@ namespace chaiscript Type_Info& operator=(const Type_Info&) = default; - CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info < ti.m_type_info; } - CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool operator==(const Type_Info &ti) const CHAISCRIPT_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 + bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info != nullptr && (*m_type_info) == ti; } - CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT + bool bare_equal(const Type_Info &ti) const CHAISCRIPT_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 + bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_bare_type_info != nullptr && (*m_bare_type_info) == ti; } - CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } - CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } - CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } - CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } - CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } - CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } + bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } + bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } + bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } + bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } + bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } + bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const { @@ -110,7 +110,7 @@ namespace chaiscript } } - CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const + const std::type_info *bare_type_info() const { return m_bare_type_info; } @@ -134,7 +134,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::type>::type>::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -149,7 +149,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -164,7 +164,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -179,7 +179,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -194,7 +194,7 @@ namespace chaiscript { typedef T type; - CHAISCRIPT_CONSTEXPR static Type_Info get() + static Type_Info get() { return Type_Info(std::is_const::value, std::is_reference::value, std::is_pointer::value, std::is_void::value, @@ -216,7 +216,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(i); /// \endcode template - CHAISCRIPT_CONSTEXPR Type_Info user_type(const T &/*t*/) + Type_Info user_type(const T &/*t*/) { return detail::Get_Type_Info::get(); } @@ -231,7 +231,7 @@ namespace chaiscript /// chaiscript::Type_Info ti = chaiscript::user_type(); /// \endcode template - CHAISCRIPT_CONSTEXPR Type_Info user_type() + Type_Info user_type() { return detail::Get_Type_Info::get(); }