From a8283e0ed2d3e42ba8e1c42f51cb08eacc301047 Mon Sep 17 00:00:00 2001 From: Christoph Hertzberg Date: Tue, 22 Jul 2014 13:16:44 +0200 Subject: Define EIGEN_TRY, EIGEN_CATCH, EIGEN_THROW as suggested by Moritz Klammer. Make it possible to run unit-tests with exceptions disabled via EIGEN_TEST_NO_EXCEPTIONS flag. Enhanced ctorleak unit-test --- CMakeLists.txt | 8 ++- Eigen/Core | 16 ++--- Eigen/src/Core/util/Macros.h | 12 ++++ Eigen/src/Core/util/Memory.h | 145 +++++++++++++++++-------------------------- test/CMakeLists.txt | 10 +-- test/ctorleak.cpp | 40 ++++-------- test/main.h | 16 +++-- 7 files changed, 112 insertions(+), 135 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 470095680..96d6c8701 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ endmacro(ei_add_cxx_compiler_flag) if(NOT MSVC) # We assume that other compilers are partly compatible with GNUCC - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") set(CMAKE_CXX_FLAGS_DEBUG "-g3") set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O2") @@ -301,6 +301,12 @@ if(EIGEN_TEST_NO_EXPLICIT_ALIGNMENT) message(STATUS "Disabling alignment in tests/examples") endif() +option(EIGEN_TEST_NO_EXCEPTIONS "Disables C++ exceptions" OFF) +if(EIGEN_TEST_NO_EXCEPTIONS) + ei_add_cxx_compiler_flag("-fno-exceptions") + message(STATUS "Disabling exceptions in tests/examples") +endif() + option(EIGEN_TEST_C++0x "Enables all C++0x features." OFF) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/Eigen/Core b/Eigen/Core index 16e388fa4..9a73fe37b 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -42,6 +42,14 @@ #define EIGEN_USING_STD_MATH(FUNC) using std::FUNC; #endif +#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) + #define EIGEN_EXCEPTIONS +#endif + +#ifdef EIGEN_EXCEPTIONS + #include +#endif + // then include this file where all our macros are defined. It's really important to do it first because // it's where we do all the alignment settings (platform detection and honoring the user's will if he // defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization. @@ -209,14 +217,6 @@ #include #endif -#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) - #define EIGEN_EXCEPTIONS -#endif - -#ifdef EIGEN_EXCEPTIONS - #include -#endif - /** \brief Namespace containing all symbols from the %Eigen library. */ namespace Eigen { diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index 71e42b125..5e9b0a112 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -452,4 +452,16 @@ namespace Eigen { const RHS \ > +#ifdef EIGEN_EXCEPTIONS +# define EIGEN_THROW_X(X) throw X +# define EIGEN_THROW throw +# define EIGEN_TRY try +# define EIGEN_CATCH(X) catch (X) +#else +# define EIGEN_THROW_X(X) std::abort() +# define EIGEN_THROW std::abort() +# define EIGEN_TRY if (true) +# define EIGEN_CATCH(X) else +#endif + #endif // EIGEN_MACROS_H diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 9b3e84fb0..38990566d 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -354,20 +354,16 @@ template inline void destruct_elements_of_array(T *ptr, size_t size) template inline T* construct_elements_of_array(T *ptr, size_t size) { size_t i; -#ifdef EIGEN_EXCEPTIONS - try -#endif - { + EIGEN_TRY + { for (i = 0; i < size; ++i) ::new (ptr + i) T; return ptr; - } -#ifdef EIGEN_EXCEPTIONS - catch (...) - { - destruct_elements_of_array(ptr, i); - throw; - } -#endif + } + EIGEN_CATCH(...) + { + destruct_elements_of_array(ptr, i); + EIGEN_THROW; + } } /***************************************************************************** @@ -389,38 +385,30 @@ template inline T* aligned_new(size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(aligned_malloc(sizeof(T)*size)); -#ifdef EIGEN_EXCEPTIONS - try -#endif - { - return construct_elements_of_array(result, size); - } -#ifdef EIGEN_EXCEPTIONS - catch (...) - { - aligned_free(result); - throw; - } -#endif + EIGEN_TRY + { + return construct_elements_of_array(result, size); + } + EIGEN_CATCH(...) + { + aligned_free(result); + EIGEN_THROW; + } } template inline T* conditional_aligned_new(size_t size) { check_size_for_overflow(size); T *result = reinterpret_cast(conditional_aligned_malloc(sizeof(T)*size)); -#ifdef EIGEN_EXCEPTIONS - try -#endif - { - return construct_elements_of_array(result, size); - } -#ifdef EIGEN_EXCEPTIONS - catch (...) - { - conditional_aligned_free(result); - throw; - } -#endif + EIGEN_TRY + { + return construct_elements_of_array(result, size); + } + EIGEN_CATCH(...) + { + conditional_aligned_free(result); + EIGEN_THROW; + } } /** \internal Deletes objects constructed with aligned_new @@ -449,21 +437,17 @@ template inline T* conditional_aligned_realloc_new(T* pt destruct_elements_of_array(pts+new_size, old_size-new_size); T *result = reinterpret_cast(conditional_aligned_realloc(reinterpret_cast(pts), sizeof(T)*new_size, sizeof(T)*old_size)); if(new_size > old_size) + { + EIGEN_TRY { -#ifdef EIGEN_EXCEPTIONS - try -#endif - { - construct_elements_of_array(result+old_size, new_size-old_size); - } -#ifdef EIGEN_EXCEPTIONS - catch (...) - { - conditional_aligned_free(result); - throw; - } -#endif + construct_elements_of_array(result+old_size, new_size-old_size); + } + EIGEN_CATCH(...) + { + conditional_aligned_free(result); + EIGEN_THROW; } + } return result; } @@ -473,21 +457,17 @@ template inline T* conditional_aligned_new_auto(size_t s check_size_for_overflow(size); T *result = reinterpret_cast(conditional_aligned_malloc(sizeof(T)*size)); if(NumTraits::RequireInitialization) + { + EIGEN_TRY { -#ifdef EIGEN_EXCEPTIONS - try -#endif - { - construct_elements_of_array(result, size); - } -#ifdef EIGEN_EXCEPTIONS - catch (...) - { - conditional_aligned_free(result); - throw; - } -#endif + construct_elements_of_array(result, size); } + EIGEN_CATCH(...) + { + conditional_aligned_free(result); + EIGEN_THROW; + } + } return result; } @@ -499,21 +479,17 @@ template inline T* conditional_aligned_realloc_new_auto( destruct_elements_of_array(pts+new_size, old_size-new_size); T *result = reinterpret_cast(conditional_aligned_realloc(reinterpret_cast(pts), sizeof(T)*new_size, sizeof(T)*old_size)); if(NumTraits::RequireInitialization && (new_size > old_size)) + { + EIGEN_TRY { -#ifdef EIGEN_EXCEPTIONS - try -#endif - { - construct_elements_of_array(result+old_size, new_size-old_size); - } -#ifdef EIGEN_EXCEPTIONS - catch (...) - { - conditional_aligned_free(result); - throw; - } -#endif + construct_elements_of_array(result+old_size, new_size-old_size); + } + EIGEN_CATCH(...) + { + conditional_aligned_free(result); + EIGEN_THROW; } + } return result; } @@ -713,20 +689,11 @@ template class aligned_stack_memory_handler *****************************************************************************/ #if EIGEN_ALIGN - #ifdef EIGEN_EXCEPTIONS - #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ - void* operator new(size_t size, const std::nothrow_t&) throw() { \ - try { return Eigen::internal::conditional_aligned_malloc(size); } \ - catch (...) { return 0; } \ - return 0; \ - } - #else - #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ + #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ void* operator new(size_t size, const std::nothrow_t&) throw() { \ - return Eigen::internal::conditional_aligned_malloc(size); \ + EIGEN_TRY { return Eigen::internal::conditional_aligned_malloc(size); } \ + EIGEN_CATCH (...) { return 0; } \ } - #endif - #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \ void *operator new(size_t size) { \ return Eigen::internal::conditional_aligned_malloc(size); \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fed5c0e06..47aefddb8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -158,7 +158,9 @@ ei_add_test(basicstuff) ei_add_test(linearstructure) ei_add_test(integer_types) ei_add_test(unalignedcount) -ei_add_test(exceptions) +if(NOT EIGEN_TEST_NO_EXCEPTIONS) + ei_add_test(exceptions) +endif() ei_add_test(redux) ei_add_test(visitor) ei_add_test(block) @@ -238,7 +240,9 @@ ei_add_test(nesting_ops "${CMAKE_CXX_FLAGS_DEBUG}") ei_add_test(zerosized) ei_add_test(dontalign) ei_add_test(evaluators) -ei_add_test(sizeoverflow) +if(NOT EIGEN_TEST_NO_EXCEPTIONS) + ei_add_test(sizeoverflow) +endif() ei_add_test(prec_inverse_4x4) ei_add_test(vectorwiseop) ei_add_test(special_numbers) @@ -251,8 +255,6 @@ ei_add_test(bicgstab) ei_add_test(sparselu) ei_add_test(sparseqr) -ei_add_test(ctorleak) - # ei_add_test(denseLM) if(QT4_FOUND) diff --git a/test/ctorleak.cpp b/test/ctorleak.cpp index f3f4411c8..145d91be4 100644 --- a/test/ctorleak.cpp +++ b/test/ctorleak.cpp @@ -28,42 +28,24 @@ struct Foo unsigned Foo::object_count = 0; unsigned Foo::object_limit = 0; -namespace Eigen -{ - template<> - struct NumTraits - { - typedef double Real; - typedef double NonInteger; - typedef double Nested; - enum - { - IsComplex = 0, - IsInteger = 1, - ReadCost = -1, - AddCost = -1, - MulCost = -1, - IsSigned = 1, - RequireInitialization = 1 - }; - static inline Real epsilon() { return 1.0; } - static inline Real dummy_epsilon() { return 0.0; } - }; -} void test_ctorleak() { + typedef DenseIndex Index; Foo::object_count = 0; - Foo::object_limit = internal::random(0, 14 * 92 - 2); + for(int i = 0; i < g_repeat; i++) { + Index rows = internal::random(2,EIGEN_TEST_MAX_SIZE), cols = internal::random(2,EIGEN_TEST_MAX_SIZE); + Foo::object_limit = internal::random(0, rows*cols - 2); #ifdef EIGEN_EXCEPTIONS - try -#endif + try { - Matrix m(14, 92); - eigen_assert(false); // not reached - } +#endif + Matrix m(rows, cols); #ifdef EIGEN_EXCEPTIONS - catch (const Foo::Fail&) { /* ignore */ } + VERIFY(false); // not reached if exceptions are enabled + } + catch (const Foo::Fail&) { /* ignore */ } #endif + } VERIFY_IS_EQUAL(static_cast(0), Foo::object_count); } diff --git a/test/main.h b/test/main.h index 3ccc2ae88..3295dcb71 100644 --- a/test/main.h +++ b/test/main.h @@ -117,13 +117,14 @@ namespace Eigen if(report_on_cerr_on_assert_failure) \ std::cerr << #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \ Eigen::no_more_assert = true; \ - throw Eigen::eigen_assert_exception(); \ + EIGEN_THROW_X(Eigen::eigen_assert_exception()); \ } \ else if (Eigen::internal::push_assert) \ { \ eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__) " (" EI_PP_MAKE_STRING(__LINE__) ") : " #a) ); \ } + #ifdef EIGEN_EXCEPTIONS #define VERIFY_RAISES_ASSERT(a) \ { \ Eigen::no_more_assert = false; \ @@ -142,6 +143,7 @@ namespace Eigen Eigen::report_on_cerr_on_assert_failure = true; \ Eigen::internal::push_assert = false; \ } + #endif //EIGEN_EXCEPTIONS #elif !defined(__CUDACC__) // EIGEN_DEBUG_ASSERTS // see bug 89. The copy_bool here is working around a bug in gcc <= 4.3 @@ -152,9 +154,10 @@ namespace Eigen if(report_on_cerr_on_assert_failure) \ eigen_plain_assert(a); \ else \ - throw Eigen::eigen_assert_exception(); \ + EIGEN_THROW_X(Eigen::eigen_assert_exception()); \ } - #define VERIFY_RAISES_ASSERT(a) { \ + #ifdef EIGEN_EXCEPTIONS + #define VERIFY_RAISES_ASSERT(a) { \ Eigen::no_more_assert = false; \ Eigen::report_on_cerr_on_assert_failure = false; \ try { \ @@ -164,9 +167,14 @@ namespace Eigen catch (Eigen::eigen_assert_exception&) { VERIFY(true); } \ Eigen::report_on_cerr_on_assert_failure = true; \ } - + #endif //EIGEN_EXCEPTIONS #endif // EIGEN_DEBUG_ASSERTS +#ifndef VERIFY_RAISES_ASSERT + #define VERIFY_RAISES_ASSERT(a) \ + std::cout << "Can't VERIFY_RAISES_ASSERT( " #a " ) with exceptions disabled"; +#endif + #if !defined(__CUDACC__) #define EIGEN_USE_CUSTOM_ASSERT #endif -- cgit v1.2.3