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
This commit is contained in:
Christoph Hertzberg 2014-07-22 13:16:44 +02:00
parent 529e6cb552
commit a8283e0ed2
7 changed files with 113 additions and 136 deletions

View File

@ -119,7 +119,7 @@ endmacro(ei_add_cxx_compiler_flag)
if(NOT MSVC) if(NOT MSVC)
# We assume that other compilers are partly compatible with GNUCC # 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_DEBUG "-g3")
set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O2") set(CMAKE_CXX_FLAGS_RELEASE "-g0 -O2")
@ -301,6 +301,12 @@ if(EIGEN_TEST_NO_EXPLICIT_ALIGNMENT)
message(STATUS "Disabling alignment in tests/examples") message(STATUS "Disabling alignment in tests/examples")
endif() 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) option(EIGEN_TEST_C++0x "Enables all C++0x features." OFF)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})

View File

@ -42,6 +42,14 @@
#define EIGEN_USING_STD_MATH(FUNC) using std::FUNC; #define EIGEN_USING_STD_MATH(FUNC) using std::FUNC;
#endif #endif
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__)
#define EIGEN_EXCEPTIONS
#endif
#ifdef EIGEN_EXCEPTIONS
#include <new>
#endif
// then include this file where all our macros are defined. It's really important to do it first because // 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 // 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. // defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization.
@ -209,14 +217,6 @@
#include <intrin.h> #include <intrin.h>
#endif #endif
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__)
#define EIGEN_EXCEPTIONS
#endif
#ifdef EIGEN_EXCEPTIONS
#include <new>
#endif
/** \brief Namespace containing all symbols from the %Eigen library. */ /** \brief Namespace containing all symbols from the %Eigen library. */
namespace Eigen { namespace Eigen {

View File

@ -452,4 +452,16 @@ namespace Eigen {
const RHS \ 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 #endif // EIGEN_MACROS_H

View File

@ -354,20 +354,16 @@ template<typename T> inline void destruct_elements_of_array(T *ptr, size_t size)
template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size) template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size)
{ {
size_t i; size_t i;
#ifdef EIGEN_EXCEPTIONS EIGEN_TRY
try {
#endif
{
for (i = 0; i < size; ++i) ::new (ptr + i) T; for (i = 0; i < size; ++i) ::new (ptr + i) T;
return ptr; return ptr;
} }
#ifdef EIGEN_EXCEPTIONS EIGEN_CATCH(...)
catch (...) {
{ destruct_elements_of_array(ptr, i);
destruct_elements_of_array(ptr, i); EIGEN_THROW;
throw; }
}
#endif
} }
/***************************************************************************** /*****************************************************************************
@ -389,38 +385,30 @@ template<typename T> inline T* aligned_new(size_t size)
{ {
check_size_for_overflow<T>(size); check_size_for_overflow<T>(size);
T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size)); T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
#ifdef EIGEN_EXCEPTIONS EIGEN_TRY
try {
#endif return construct_elements_of_array(result, size);
{ }
return construct_elements_of_array(result, size); EIGEN_CATCH(...)
} {
#ifdef EIGEN_EXCEPTIONS aligned_free(result);
catch (...) EIGEN_THROW;
{ }
aligned_free(result);
throw;
}
#endif
} }
template<typename T, bool Align> inline T* conditional_aligned_new(size_t size) template<typename T, bool Align> inline T* conditional_aligned_new(size_t size)
{ {
check_size_for_overflow<T>(size); check_size_for_overflow<T>(size);
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size)); T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
#ifdef EIGEN_EXCEPTIONS EIGEN_TRY
try {
#endif return construct_elements_of_array(result, size);
{ }
return construct_elements_of_array(result, size); EIGEN_CATCH(...)
} {
#ifdef EIGEN_EXCEPTIONS conditional_aligned_free<Align>(result);
catch (...) EIGEN_THROW;
{ }
conditional_aligned_free<Align>(result);
throw;
}
#endif
} }
/** \internal Deletes objects constructed with aligned_new /** \internal Deletes objects constructed with aligned_new
@ -449,21 +437,17 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pt
destruct_elements_of_array(pts+new_size, old_size-new_size); destruct_elements_of_array(pts+new_size, old_size-new_size);
T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size)); T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
if(new_size > old_size) if(new_size > old_size)
{
EIGEN_TRY
{ {
#ifdef EIGEN_EXCEPTIONS construct_elements_of_array(result+old_size, new_size-old_size);
try
#endif
{
construct_elements_of_array(result+old_size, new_size-old_size);
}
#ifdef EIGEN_EXCEPTIONS
catch (...)
{
conditional_aligned_free<Align>(result);
throw;
}
#endif
} }
EIGEN_CATCH(...)
{
conditional_aligned_free<Align>(result);
EIGEN_THROW;
}
}
return result; return result;
} }
@ -473,21 +457,17 @@ template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t s
check_size_for_overflow<T>(size); check_size_for_overflow<T>(size);
T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size)); T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
if(NumTraits<T>::RequireInitialization) if(NumTraits<T>::RequireInitialization)
{
EIGEN_TRY
{ {
#ifdef EIGEN_EXCEPTIONS construct_elements_of_array(result, size);
try
#endif
{
construct_elements_of_array(result, size);
}
#ifdef EIGEN_EXCEPTIONS
catch (...)
{
conditional_aligned_free<Align>(result);
throw;
}
#endif
} }
EIGEN_CATCH(...)
{
conditional_aligned_free<Align>(result);
EIGEN_THROW;
}
}
return result; return result;
} }
@ -499,21 +479,17 @@ template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(
destruct_elements_of_array(pts+new_size, old_size-new_size); destruct_elements_of_array(pts+new_size, old_size-new_size);
T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size)); T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
if(NumTraits<T>::RequireInitialization && (new_size > old_size)) if(NumTraits<T>::RequireInitialization && (new_size > old_size))
{
EIGEN_TRY
{ {
#ifdef EIGEN_EXCEPTIONS construct_elements_of_array(result+old_size, new_size-old_size);
try
#endif
{
construct_elements_of_array(result+old_size, new_size-old_size);
}
#ifdef EIGEN_EXCEPTIONS
catch (...)
{
conditional_aligned_free<Align>(result);
throw;
}
#endif
} }
EIGEN_CATCH(...)
{
conditional_aligned_free<Align>(result);
EIGEN_THROW;
}
}
return result; return result;
} }
@ -713,20 +689,11 @@ template<typename T> class aligned_stack_memory_handler
*****************************************************************************/ *****************************************************************************/
#if EIGEN_ALIGN #if EIGEN_ALIGN
#ifdef EIGEN_EXCEPTIONS #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() { \ void* operator new(size_t size, const std::nothrow_t&) throw() { \
try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \ EIGEN_TRY { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
catch (...) { return 0; } \ EIGEN_CATCH (...) { return 0; } \
return 0; \
} }
#else
#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<NeedsToAlign>(size); \
}
#endif
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \ #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
void *operator new(size_t size) { \ void *operator new(size_t size) { \
return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \ return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \

View File

@ -158,7 +158,9 @@ ei_add_test(basicstuff)
ei_add_test(linearstructure) ei_add_test(linearstructure)
ei_add_test(integer_types) ei_add_test(integer_types)
ei_add_test(unalignedcount) 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(redux)
ei_add_test(visitor) ei_add_test(visitor)
ei_add_test(block) ei_add_test(block)
@ -238,7 +240,9 @@ ei_add_test(nesting_ops "${CMAKE_CXX_FLAGS_DEBUG}")
ei_add_test(zerosized) ei_add_test(zerosized)
ei_add_test(dontalign) ei_add_test(dontalign)
ei_add_test(evaluators) 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(prec_inverse_4x4)
ei_add_test(vectorwiseop) ei_add_test(vectorwiseop)
ei_add_test(special_numbers) ei_add_test(special_numbers)
@ -251,8 +255,6 @@ ei_add_test(bicgstab)
ei_add_test(sparselu) ei_add_test(sparselu)
ei_add_test(sparseqr) ei_add_test(sparseqr)
ei_add_test(ctorleak)
# ei_add_test(denseLM) # ei_add_test(denseLM)
if(QT4_FOUND) if(QT4_FOUND)

View File

@ -28,42 +28,24 @@ struct Foo
unsigned Foo::object_count = 0; unsigned Foo::object_count = 0;
unsigned Foo::object_limit = 0; unsigned Foo::object_limit = 0;
namespace Eigen
{
template<>
struct NumTraits<Foo>
{
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() void test_ctorleak()
{ {
typedef DenseIndex Index;
Foo::object_count = 0; 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<Index>(2,EIGEN_TEST_MAX_SIZE), cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
Foo::object_limit = internal::random(0, rows*cols - 2);
#ifdef EIGEN_EXCEPTIONS #ifdef EIGEN_EXCEPTIONS
try try
#endif
{ {
Matrix<Foo, Dynamic, Dynamic> m(14, 92);
eigen_assert(false); // not reached
}
#ifdef EIGEN_EXCEPTIONS
catch (const Foo::Fail&) { /* ignore */ }
#endif #endif
Matrix<Foo, Dynamic, Dynamic> m(rows, cols);
#ifdef EIGEN_EXCEPTIONS
VERIFY(false); // not reached if exceptions are enabled
}
catch (const Foo::Fail&) { /* ignore */ }
#endif
}
VERIFY_IS_EQUAL(static_cast<unsigned>(0), Foo::object_count); VERIFY_IS_EQUAL(static_cast<unsigned>(0), Foo::object_count);
} }

View File

@ -117,13 +117,14 @@ namespace Eigen
if(report_on_cerr_on_assert_failure) \ if(report_on_cerr_on_assert_failure) \
std::cerr << #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \ std::cerr << #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \
Eigen::no_more_assert = true; \ Eigen::no_more_assert = true; \
throw Eigen::eigen_assert_exception(); \ EIGEN_THROW_X(Eigen::eigen_assert_exception()); \
} \ } \
else if (Eigen::internal::push_assert) \ else if (Eigen::internal::push_assert) \
{ \ { \
eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__) " (" EI_PP_MAKE_STRING(__LINE__) ") : " #a) ); \ 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) \ #define VERIFY_RAISES_ASSERT(a) \
{ \ { \
Eigen::no_more_assert = false; \ Eigen::no_more_assert = false; \
@ -142,6 +143,7 @@ namespace Eigen
Eigen::report_on_cerr_on_assert_failure = true; \ Eigen::report_on_cerr_on_assert_failure = true; \
Eigen::internal::push_assert = false; \ Eigen::internal::push_assert = false; \
} }
#endif //EIGEN_EXCEPTIONS
#elif !defined(__CUDACC__) // EIGEN_DEBUG_ASSERTS #elif !defined(__CUDACC__) // EIGEN_DEBUG_ASSERTS
// see bug 89. The copy_bool here is working around a bug in gcc <= 4.3 // 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) \ if(report_on_cerr_on_assert_failure) \
eigen_plain_assert(a); \ eigen_plain_assert(a); \
else \ 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::no_more_assert = false; \
Eigen::report_on_cerr_on_assert_failure = false; \ Eigen::report_on_cerr_on_assert_failure = false; \
try { \ try { \
@ -164,9 +167,14 @@ namespace Eigen
catch (Eigen::eigen_assert_exception&) { VERIFY(true); } \ catch (Eigen::eigen_assert_exception&) { VERIFY(true); } \
Eigen::report_on_cerr_on_assert_failure = true; \ Eigen::report_on_cerr_on_assert_failure = true; \
} }
#endif //EIGEN_EXCEPTIONS
#endif // EIGEN_DEBUG_ASSERTS #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__) #if !defined(__CUDACC__)
#define EIGEN_USE_CUSTOM_ASSERT #define EIGEN_USE_CUSTOM_ASSERT
#endif #endif