2727
2828#include " memfault/config.h"
2929
30- #ifdef __cplusplus
31- extern "C" {
32- #endif
33-
3430#if MEMFAULT_COMPACT_LOG_ENABLE
3531
3632#include " memfault/core/compiler.h"
@@ -43,16 +39,52 @@ extern "C" {
4339
4440#ifdef __cplusplus
4541
42+ // C++ implementation of the type promotion logic
43+ //
44+ // Note: the C++ implementation requires the use of C++11 features and the GNU
45+ // "##" variadic arg extension. Memfault Compact Logs in C++ require the
46+ // compiler flag '--std=gnu++-11' or newer.
4647
47- #ifdef MEMFAULT_UNITTEST
48- //! Note: For trace_event Memfault CppUTest tests, we pick up this header but do not actually use
49- //! the helpers defined so let's silence the warning generated
50- #else
51- # error "Compact logs not yet available when using CPP"
52- #endif
48+ #include < type_traits>
5349
54- #else // C Code implementation
50+ // Default integer type is int64
51+ template <typename T, typename E = void >
52+ struct MemfaultLogArgPromotionType
53+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_INT64> {};
54+
55+ // If sizeof(T) <= 32, then it's int32
56+ template <typename T>
57+ struct MemfaultLogArgPromotionType <
58+ T, typename std::enable_if<sizeof (T) <= 4 >::type>
59+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_INT32> {};
60+
61+ // More specific types
62+ template <>
63+ struct MemfaultLogArgPromotionType <float >
64+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE> {};
65+
66+ template <>
67+ struct MemfaultLogArgPromotionType <double >
68+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE> {};
69+
70+ template <>
71+ struct MemfaultLogArgPromotionType <long double >
72+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE> {};
73+
74+ template <>
75+ struct MemfaultLogArgPromotionType <char *>
76+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> {};
5577
78+ template <>
79+ struct MemfaultLogArgPromotionType <const char *>
80+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> {};
81+
82+ // When expressing the final type via the template parameter expansion, operate
83+ // on (arg) + 0 to force integer promotion
84+ #define _MEMFAULT_LOG_ARG_PROMOTION_TYPE (arg ) \
85+ MemfaultLogArgPromotionType<decltype ((arg) + 0 )>::value
86+
87+ #else // C Code implementation
5688
5789// ! Preprocessor macro to encode promotion type info about each va_arg in a uint32_t
5890// !
@@ -94,6 +126,10 @@ extern "C" {
94126 default: sizeof((arg) + 0) <= sizeof(int ) ? \
95127 MEMFAULT_LOG_ARG_PROMOTED_TO_INT32 : MEMFAULT_LOG_ARG_PROMOTED_TO_INT64) \
96128
129+ #endif // __cplusplus
130+
131+ #ifdef __cplusplus
132+ extern " C" {
97133#endif
98134
99135#define _MF_FMT_0 (fmt_op ) 0
@@ -176,8 +212,8 @@ typedef struct MemfaultLogFmtElfSectionHeader {
176212
177213extern const sMemfaultLogFmtElfSectionHeader g_memfault_log_fmt_elf_section_hdr;
178214
179- #endif /* MEMFAULT_COMPACT_LOG_ENABLE */
180-
181215#ifdef __cplusplus
182216}
183217#endif
218+
219+ #endif /* MEMFAULT_COMPACT_LOG_ENABLE */
0 commit comments