diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | include/armnn/Exceptions.hpp | 17 | ||||
-rw-r--r-- | include/armnn/utility/PolymorphicDowncast.hpp | 43 | ||||
-rw-r--r-- | src/armnn/test/UtilityTests.cpp | 56 |
4 files changed, 118 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f8761aa94..046ef834ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,6 +249,7 @@ list(APPEND armnn_sources include/armnn/profiling/ISendTimelinePacket.hpp include/armnn/utility/Assert.hpp include/armnn/utility/IgnoreUnused.hpp + include/armnn/utility/PolymorphicDowncast.hpp profiling/common/include/SocketConnectionException.hpp src/armnn/layers/LayerCloneBase.hpp src/armnn/layers/LayerWithParameters.hpp @@ -648,6 +649,7 @@ if(BUILD_UNIT_TESTS) src/armnn/test/TestNameAndDescriptorLayerVisitor.cpp src/armnn/test/TestUtils.cpp src/armnn/test/TestUtils.hpp + src/armnn/test/UtilityTests.cpp src/armnn/test/UnitTests.cpp src/armnn/test/UnitTests.hpp src/armnn/test/UtilsTests.cpp diff --git a/include/armnn/Exceptions.hpp b/include/armnn/Exceptions.hpp index cb62079b76..05b740614d 100644 --- a/include/armnn/Exceptions.hpp +++ b/include/armnn/Exceptions.hpp @@ -143,6 +143,13 @@ public: using Exception::Exception; }; +class PolymorphicDowncastException : public Exception +{ +public: + using Exception::Exception; +}; + + template <typename ExceptionType> void ConditionalThrow(bool condition, const std::string& message) { @@ -152,6 +159,16 @@ void ConditionalThrow(bool condition, const std::string& message) } } +template <typename ExceptionType> +void ConditionalThrow(bool condition) +{ + if (!condition) + { + throw ExceptionType(); + } +} + + /// /// ComparedType must support: /// operator==(const ComparedType&) diff --git a/include/armnn/utility/PolymorphicDowncast.hpp b/include/armnn/utility/PolymorphicDowncast.hpp new file mode 100644 index 0000000000..d529867474 --- /dev/null +++ b/include/armnn/utility/PolymorphicDowncast.hpp @@ -0,0 +1,43 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "Assert.hpp" + +#include <armnn/Exceptions.hpp> + +#include <type_traits> + +namespace armnn +{ + +// If we are testing then throw an exception, otherwise regular assert +#if defined(ARMNN_POLYMORPHIC_CAST_TESTABLE) +# define ARMNN_POLYMORPHIC_CAST_CHECK_METHOD(cond) ConditionalThrow<std::bad_cast>(cond) +#else +# define ARMNN_POLYMORPHIC_CAST_CHECK_METHOD(cond) ARMNN_ASSERT(cond) +#endif + +//Only check the condition if debug build or during testing +#if !defined(NDEBUG) || defined(ARMNN_POLYMORPHIC_CAST_TESTABLE) +# define ARMNN_POLYMORPHIC_CAST_CHECK(cond) ARMNN_POLYMORPHIC_CAST_CHECK_METHOD(cond) +#else +# define ARMNN_POLYMORPHIC_CAST_CHECK(cond) // release builds dont check the cast +#endif + + +template<typename DestType, typename SourceType> +DestType polymorphic_downcast(SourceType value) +{ + static_assert(std::is_pointer<SourceType>::value && + std::is_pointer<DestType>::value, + "polymorphic_downcast only works with pointer types."); + + ARMNN_POLYMORPHIC_CAST_CHECK(dynamic_cast<DestType>(value) == static_cast<DestType>(value)); + return static_cast<DestType>(value); +} + +} //namespace armnn
\ No newline at end of file diff --git a/src/armnn/test/UtilityTests.cpp b/src/armnn/test/UtilityTests.cpp new file mode 100644 index 0000000000..5309d82ce4 --- /dev/null +++ b/src/armnn/test/UtilityTests.cpp @@ -0,0 +1,56 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include <boost/test/unit_test.hpp> +#include <boost/core/lightweight_test.hpp> +#include <boost/polymorphic_cast.hpp> + +#define ARMNN_POLYMORPHIC_CAST_TESTABLE + +#include <armnn/utility/IgnoreUnused.hpp> +#include <armnn/utility/PolymorphicDowncast.hpp> + +#include <armnn/Exceptions.hpp> + +// Tests of include/Utility files +BOOST_AUTO_TEST_SUITE(UtilityTests) + +BOOST_AUTO_TEST_CASE(PolymorphicDowncast) +{ + using namespace armnn; + class Base + { + public: + virtual ~Base(){} + float v; + }; + + class Child1 : public Base + { + public: + int j; + }; + + class Child2 : public Base + { + public: + char b; + }; + + Child1 child1; + Base* base1 = &child1; + auto ptr1 = dynamic_cast<Child1*>(base1); + BOOST_CHECK(ptr1 != nullptr); + BOOST_CHECK_NO_THROW(polymorphic_downcast<Child1*>(base1)); + BOOST_CHECK(polymorphic_downcast<Child1*>(base1) == ptr1); + + auto ptr2 = dynamic_cast<Child2*>(base1); + BOOST_CHECK(ptr2 == nullptr); + BOOST_CHECK_THROW(polymorphic_downcast<Child2*>(base1), std::bad_cast); + + armnn::IgnoreUnused(ptr1, ptr2); +} + +BOOST_AUTO_TEST_SUITE_END() |