39
39
40
40
#ifdef __cplusplus
41
41
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.
42
+ // ! C++ type promotion logic
43
+ // !
44
+ // ! This code defines the MemfaultLogArgPromotionType template structure, responsible for
45
+ // ! determining the promotion type of different argument types passed to Memfault's logging
46
+ // ! functions. This is important because certain types may need to be promoted to larger or
47
+ // ! different types, ensuring consistent handling in logging The code uses C++11 features,
48
+ // ! including SFINAE (Substitution Failure Is Not An Error) with std::enable_if, and the GNU ## va
49
+ // ! args extension. It assumes the --std=gnu++11 compiler flag or newer.
50
+ // !
51
+ // ! Structure definition:
52
+ // ! 1. Default promotion to int64:
53
+ // ! - By default, if no other promotion rule applies, MemfaultLogArgPromotionType promotes the
54
+ // ! type to
55
+ // ! MEMFAULT_LOG_ARG_PROMOTED_TO_INT64, indicating that any unhandled type defaults to a
56
+ // ! 64-bit integer.
57
+ // !
58
+ // ! 2. Conditional promotion to int32:
59
+ // ! - If the size of the type T is less than or equal to 4 bytes (e.g., smaller integer types),
60
+ // ! MemfaultLogArgPromotionType promotes the type to MEMFAULT_LOG_ARG_PROMOTED_TO_INT32,
61
+ // ! allowing consistent handling for smaller integers.
62
+ // !
63
+ // ! 3. Specialized promotions:
64
+ // ! - Specific types receive unique promotion constants:
65
+ // ! - Floating-point types (float, double, long double): Promoted to
66
+ // ! MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE.
67
+ // ! - String types (char* variants): Promoted to MEMFAULT_LOG_ARG_PROMOTED_TO_STR.
68
+ // !
69
+ // ! Macro definition:
70
+ // ! - _MEMFAULT_LOG_ARG_PROMOTION_TYPE(arg): This macro determines the promotion type of an
71
+ // ! argument.
72
+ // ! The (arg) + 0 operation is used to enforce integer promotion for non-integer types, helping
73
+ // ! the compiler resolve the appropriate type for MemfaultLogArgPromotionType.
47
74
48
75
#include < type_traits>
49
76
@@ -78,22 +105,43 @@ template <>
78
105
struct MemfaultLogArgPromotionType <const char *>
79
106
: std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> { };
80
107
81
- // When expressing the final type via the template parameter expansion, operate
82
- // on (arg) + 0 to force integer promotion
108
+ template <>
109
+ struct MemfaultLogArgPromotionType <signed char *>
110
+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> { };
111
+
112
+ template <>
113
+ struct MemfaultLogArgPromotionType <const signed char *>
114
+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> { };
115
+
116
+ template <>
117
+ struct MemfaultLogArgPromotionType <unsigned char *>
118
+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> { };
119
+
120
+ template <>
121
+ struct MemfaultLogArgPromotionType <const unsigned char *>
122
+ : std::integral_constant<int , MEMFAULT_LOG_ARG_PROMOTED_TO_STR> { };
123
+
83
124
#define _MEMFAULT_LOG_ARG_PROMOTION_TYPE (arg ) \
84
125
MemfaultLogArgPromotionType<decltype ((arg) + 0 )>::value
85
126
86
127
#else // C Code implementation
87
128
88
- // ! Preprocessor macro to encode promotion type info about each va_arg in a uint32_t
129
+ // ! C type promotion logic
89
130
// !
90
131
// ! Utilizes the rules around "default argument promotion" (specifically for va_args) defined in
91
132
// ! the C specification (http://www.iso-9899.info/wiki/The_Standard) to encode information about
92
133
// ! the width of arguments. (For more details see "6.5.2.2 Function calls" in the C11 Spec).
93
134
// !
94
- // ! In short,
95
- // ! - floats are always promoted to doubles
96
- // ! - any other type < sizeof(int) is promoted to the width of an int
135
+ // ! Promotion Rules:
136
+ // ! - Floating-point types (float, double, long double): Promoted to
137
+ // ! MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE.
138
+ // ! - String types (char* variants): Promoted to MEMFAULT_LOG_ARG_PROMOTED_TO_STR.
139
+ // ! - Default case:
140
+ // ! - If the size of the argument is less than or equal to the size of an int, the type is
141
+ // ! promoted to
142
+ // ! MEMFAULT_LOG_ARG_PROMOTED_TO_INT32.
143
+ // ! - Otherwise, it defaults to MEMFAULT_LOG_ARG_PROMOTED_TO_INT64, for larger integer types.
144
+ // ! - Notably, bool and _BitInt(N) are safely promoted to int by falling into this case.
97
145
// !
98
146
// ! NOTE 1: We use a special type for "strings" (i.e char *) so we know to encode the value
99
147
// ! pointed to (the actual NUL terminated string) in this situation rather than the pointer
@@ -118,15 +166,19 @@ struct MemfaultLogArgPromotionType<const char *>
118
166
119
167
// clang-format off
120
168
121
- #define _MEMFAULT_LOG_ARG_PROMOTION_TYPE (arg ) \
122
- _Generic ((arg) + 0, \
123
- float: MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE, \
124
- double: MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE, \
125
- long double: MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE, \
126
- char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
127
- const char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
128
- default: sizeof((arg) + 0) <= sizeof(int ) ? \
129
- MEMFAULT_LOG_ARG_PROMOTED_TO_INT32 : MEMFAULT_LOG_ARG_PROMOTED_TO_INT64)
169
+ #define _MEMFAULT_LOG_ARG_PROMOTION_TYPE (arg ) \
170
+ _Generic ((arg) + 0, \
171
+ float: MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE, \
172
+ double: MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE, \
173
+ long double: MEMFAULT_LOG_ARG_PROMOTED_TO_DOUBLE, \
174
+ char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
175
+ const char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
176
+ signed char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
177
+ const signed char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
178
+ unsigned char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
179
+ const unsigned char*: MEMFAULT_LOG_ARG_PROMOTED_TO_STR, \
180
+ default: sizeof((arg) + 0) <= sizeof(int ) ? \
181
+ MEMFAULT_LOG_ARG_PROMOTED_TO_INT32 : MEMFAULT_LOG_ARG_PROMOTED_TO_INT64)
130
182
131
183
// clang-format on
132
184
0 commit comments