diff --git a/include/etl/platform.h b/include/etl/platform.h index 56ab83103..0583d17ae 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -460,6 +460,22 @@ SOFTWARE. #define ETL_HAS_INITIALIZER_LIST 0 #endif +//************************************* +// Determine if the ETL should use __attribute__((packed). +#if defined(ETL_COMPILER_CLANG) || defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_INTEL) || defined(ETL_COMPILER_ARM6) + #define ETL_PACKED __attribute__((packed)) + #define ETL_END_PACKED + #define ETL_HAS_PACKED 1 +#elif defined(ETL_COMPILER_MICROSOFT) + #define ETL_PACKED __pragma(pack(push, 1)) + #define ETL_END_PACKED __pragma(pack(pop)) + #define ETL_HAS_PACKED 1 +#else + #define ETL_PACKED + #define ETL_END_PACKED + #define ETL_HAS_PACKED 0 +#endif + //************************************* // Check for availability of certain builtins #include "profiles/determine_builtin_support.h" @@ -518,6 +534,7 @@ namespace etl static ETL_CONSTANT bool has_mutable_array_view = (ETL_HAS_MUTABLE_ARRAY_VIEW == 1); static ETL_CONSTANT bool has_ideque_repair = (ETL_HAS_IDEQUE_REPAIR == 1); static ETL_CONSTANT bool has_virtual_messages = (ETL_HAS_VIRTUAL_MESSAGES == 1); + static ETL_CONSTANT bool has_packed = (ETL_HAS_PACKED == 1); // Is... static ETL_CONSTANT bool is_debug_build = (ETL_IS_DEBUG_BUILD == 1); diff --git a/include/etl/unaligned_type.h b/include/etl/unaligned_type.h index 9b4ae6629..1c406ba3c 100644 --- a/include/etl/unaligned_type.h +++ b/include/etl/unaligned_type.h @@ -53,7 +53,7 @@ namespace etl /// Contains all functionality that doesn't require the type. //************************************************************************* template - class unaligned_type_common + class ETL_PACKED unaligned_type_common { public: @@ -214,7 +214,7 @@ namespace etl protected: unsigned char storage[Size]; - }; + }; ETL_END_PACKED template ETL_CONSTANT size_t unaligned_type_common::Size; @@ -227,7 +227,7 @@ namespace etl ///\tparam Endian The endianness of the arithmetic type. //************************************************************************* template - class unaligned_type : public private_unaligned_type::unaligned_type_common + class ETL_PACKED unaligned_type : public private_unaligned_type::unaligned_type_common { public: @@ -729,7 +729,7 @@ namespace etl } } }; - }; + }; ETL_END_PACKED template ETL_CONSTANT int unaligned_type::Endian; diff --git a/test/test_etl_traits.cpp b/test/test_etl_traits.cpp index a071960e4..24123ad3a 100644 --- a/test/test_etl_traits.cpp +++ b/test/test_etl_traits.cpp @@ -77,6 +77,7 @@ namespace CHECK_EQUAL((ETL_HAS_IDEQUE_REPAIR == 1), etl::traits::has_ideque_repair); CHECK_EQUAL((ETL_HAS_MUTABLE_ARRAY_VIEW == 1), etl::traits::has_mutable_array_view); CHECK_EQUAL((ETL_HAS_VIRTUAL_MESSAGES == 1), etl::traits::has_virtual_messages); + CHECK_EQUAL((ETL_HAS_PACKED == 1), etl::traits::has_packed); CHECK_EQUAL((ETL_IS_DEBUG_BUILD == 1), etl::traits::is_debug_build); CHECK_EQUAL(__cplusplus, etl::traits::cplusplus); diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 223058547..5d7e28091 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -718,5 +718,31 @@ namespace CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl(etl::move(u4))); CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl(etl::move(u4))); } + +#if ETL_HAS_PACKED + //********************************* + TEST(test_packed) + { + struct Unpacked + { + uint32_t a = 0x12345678; + uint8_t b = 0x9A; + uint32_t c = 0x87654321; + }; + + struct ETL_PACKED Packed + { + uint32_t a = 0x12345678; + uint8_t b = 0x9A; + uint32_t c = 0x87654321; + }; ETL_END_PACKED + + Unpacked unpacked; + Packed packed; + + CHECK_TRUE(sizeof(unpacked) > sizeof(packed)); + CHECK_EQUAL(9U, sizeof(packed)); + } +#endif }; }