From 4d4e0e2530629ae9ecfcb379bf0f27c6b18b6891 Mon Sep 17 00:00:00 2001 From: Derek Lamberti Date: Wed, 19 Feb 2020 13:30:47 +0000 Subject: IVGCVSW-4483 Introduce polymorphic_downcast implementation Change-Id: I958dd719162337eb5c7e71f4ac49dd5784564b1a Signed-off-by: Derek Lamberti --- CMakeLists.txt | 2 + include/armnn/Exceptions.hpp | 17 ++++++++ include/armnn/utility/PolymorphicDowncast.hpp | 43 ++++++++++++++++++++ src/armnn/test/UtilityTests.cpp | 56 +++++++++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 include/armnn/utility/PolymorphicDowncast.hpp create mode 100644 src/armnn/test/UtilityTests.cpp 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 void ConditionalThrow(bool condition, const std::string& message) { @@ -152,6 +159,16 @@ void ConditionalThrow(bool condition, const std::string& message) } } +template +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 + +#include + +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(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 +DestType polymorphic_downcast(SourceType value) +{ + static_assert(std::is_pointer::value && + std::is_pointer::value, + "polymorphic_downcast only works with pointer types."); + + ARMNN_POLYMORPHIC_CAST_CHECK(dynamic_cast(value) == static_cast(value)); + return static_cast(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 +#include +#include + +#define ARMNN_POLYMORPHIC_CAST_TESTABLE + +#include +#include + +#include + +// 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(base1); + BOOST_CHECK(ptr1 != nullptr); + BOOST_CHECK_NO_THROW(polymorphic_downcast(base1)); + BOOST_CHECK(polymorphic_downcast(base1) == ptr1); + + auto ptr2 = dynamic_cast(base1); + BOOST_CHECK(ptr2 == nullptr); + BOOST_CHECK_THROW(polymorphic_downcast(base1), std::bad_cast); + + armnn::IgnoreUnused(ptr1, ptr2); +} + +BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.1