• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_preprocessor:
2
3---------------
4pw_preprocessor
5---------------
6The preprocessor module provides various helpful preprocessor macros.
7
8Compatibility
9=============
10C and C++
11
12Headers
13=======
14The preprocessor module provides several headers.
15
16pw_preprocessor/arguments.h
17---------------------------------
18Defines macros for handling variadic arguments to function-like macros. Macros
19include the following:
20
21.. c:macro:: PW_DELEGATE_BY_ARG_COUNT(name, ...)
22
23  Selects and invokes a macro based on the number of arguments provided. Expands
24  to ``<name><arg_count>(...)``. For example,
25  ``PW_DELEGATE_BY_ARG_COUNT(foo_, 1, 2, 3)`` expands to ``foo_3(1, 2, 3)``.
26
27  This example shows how ``PW_DELEGATE_BY_ARG_COUNT`` could be used to log a
28  customized message based on the number of arguments provided.
29
30  .. code-block:: cpp
31
32      #define ARG_PRINT(...)  PW_DELEGATE_BY_ARG_COUNT(_ARG_PRINT, __VA_ARGS__)
33      #define _ARG_PRINT0(a)        LOG_INFO("nothing!")
34      #define _ARG_PRINT1(a)        LOG_INFO("1 arg: %s", a)
35      #define _ARG_PRINT2(a, b)     LOG_INFO("2 args: %s, %s", a, b)
36      #define _ARG_PRINT3(a, b, c)  LOG_INFO("3 args: %s, %s, %s", a, b, c)
37
38  When used, ``ARG_PRINT`` expands to the ``_ARG_PRINT#`` macro corresponding
39  to the number of arguments.
40
41  .. code-block:: cpp
42
43      ARG_PRINT();               // Outputs: nothing!
44      ARG_PRINT("a");            // Outputs: 1 arg: a
45      ARG_PRINT("a", "b");       // Outputs: 2 args: a, b
46      ARG_PRINT("a", "b", "c");  // Outputs: 3 args: a, b, c
47
48.. c:macro:: PW_COMMA_ARGS(...)
49
50  Expands to a comma followed by the arguments if any arguments are provided.
51  Otherwise, expands to nothing. If the final argument is empty, it is omitted.
52  This is useful when passing ``__VA_ARGS__`` to a variadic function or template
53  parameter list, since it removes the extra comma when no arguments are
54  provided. ``PW_COMMA_ARGS`` must NOT be used when invoking a macro from
55  another macro.
56
57  For example. ``PW_COMMA_ARGS(1, 2, 3)``, expands to ``, 1, 2, 3``, while
58  ``PW_COMMA_ARGS()`` expands to nothing. ``PW_COMMA_ARGS(1, 2, )`` expands to
59  ``, 1, 2``.
60
61pw_preprocessor/boolean.h
62-------------------------
63Defines macros for boolean logic on literal 1s and 0s. This is useful for
64situations when a literal is needed to build the name of a function or macro.
65
66pw_preprocessor/compiler.h
67--------------------------
68Macros for compiler-specific features, such as attributes or builtins.
69
70.. c:macro:: PW_PACKED(declaration)
71
72  Marks a struct or class as packed.
73
74.. c:macro:: PW_USED
75
76  Marks a function or object as used, ensuring code for it is generated.
77
78.. c:macro:: PW_NO_PROLOGUE
79
80  Prevents generation of a prologue or epilogue for a function. This is
81  helpful when implementing the function in assembly.
82
83.. c:macro:: PW_PRINTF_FORMAT(format_index, parameter_index)
84
85  Marks that a function declaration takes a printf-style format string and
86  variadic arguments. This allows the compiler to perform check the validity of
87  the format string and arguments. This macro must only be on the function
88  declaration, not the definition.
89
90  The format_index is index of the format string parameter and parameter_index
91  is the starting index of the variadic arguments. Indices start at 1. For C++
92  class member functions, add one to the index to account for the implicit this
93  parameter.
94
95  This example shows a function where the format string is argument 2 and the
96  varargs start at argument 3.
97
98  .. code-block:: cpp
99
100    int PrintfStyleFunction(char* buffer,
101                            const char* fmt, ...) PW_PRINTF_FORMAT(2,3);
102
103    int PrintfStyleFunction(char* buffer, const char* fmt, ...) {
104      ... implementation here ...
105    }
106
107.. c:macro:: PW_PLACE_IN_SECTION(name)
108
109  Places a variable in the specified linker section.
110
111.. c:macro:: PW_KEEP_IN_SECTION(name)
112
113  Places a variable in the specified linker section and directs the compiler
114  to keep the variable, even if it is not used. Depending on the linker
115  options, the linker may still remove this section if it is not declared in
116  the linker script and marked KEEP.
117
118.. c:macro:: PW_NO_RETURN
119
120  Indicate to the compiler that the annotated function won't return. Example:
121
122  .. code-block:: cpp
123
124    PW_NO_RETURN void HandleAssertFailure(ErrorCode error_code);
125
126
127.. c:macro:: PW_NO_INLINE
128
129  Prevents the compiler from inlining a fuction.
130
131.. c:macro:: PW_UNREACHABLE
132
133  Indicate to the compiler that the given section of code will not be reached.
134  Example:
135
136  .. code-block:: cpp
137
138    int main() {
139      InitializeBoard();
140      vendor_StartScheduler();  // Note: vendor forgot noreturn attribute.
141      PW_UNREACHABLE;
142    }
143
144
145.. c:macro:: PW_NO_SANITIZE(check)
146
147  Indicate to a sanitizer compiler runtime to skip the named check in the
148  associated function.
149  Example:
150
151  .. code-block:: cpp
152
153    uint32_t djb2(const void* buf, size_t len)
154        PW_NO_SANITIZE("unsigned-integer-overflow"){
155      uint32_t hash = 5381;
156      const uint8_t* u8 = static_cast<const uint8_t*>(buf);
157      for (size_t i = 0; i < len; ++i) {
158        hash = (hash * 33) + u8[i]; // hash * 33 + c
159      }
160      return hash;
161    }
162
163.. c:macro:: PW_HAVE_ATTRIBUTE(x)
164
165  Wrapper around `__has_attribute`, which is defined by GCC 5+ and Clang and
166  evaluates to a non zero constant integer if the attribute is supported or 0
167  if not.
168
169.. c:macro:: PW_HAVE_CPP_ATTRIBUTE(x)
170
171  Wrapper around `__has_cpp_attribute`, which was introduced in the C++20
172  standard. It is supported by compilers even if C++20 is not in use. Evaluates
173  to a non zero constant integer if the C++ attribute is supported or 0 if not.
174
175.. c:macro:: PW_PRAGMA(contents)
176
177  Expands to a _Pragma with the contents as a string. _Pragma must take a
178  single string literal; this can be used to construct a _Pragma argument.
179
180.. c:macro:: PW_WEAK
181
182  Marks a function or object as weak, allowing the definition to be overriden.
183
184  This can be useful when supporting third-party SDKs which may conditionally
185  compile in code, for example:
186
187  .. code-block:: cpp
188
189    PW_WEAK void SysTick_Handler(void) {
190      // Default interrupt handler that might be overriden.
191    }
192
193.. c:macro:: PW_ALIAS(aliased_to)
194
195  Marks a weak function as an alias to another, allowing the definition to
196  be given a default and overriden.
197
198  This can be useful when supporting third-party SDKs which may conditionally
199  compile in code, for example:
200
201  .. code-block:: cpp
202
203    // Driver handler replaced with default unless overridden.
204    void USART_DriverHandler(void) PW_ALIAS(DefaultDriverHandler);
205
206.. c:macro:: PW_ATTRIBUTE_LIFETIME_BOUND
207
208  PW_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
209  parameter or implicit object parameter is retained by the return value of the
210  annotated function (or, for a parameter of a constructor, in the value of the
211  constructed object). This attribute causes warnings to be produced if a
212  temporary object does not live long enough.
213
214  When applied to a reference parameter, the referenced object is assumed to be
215  retained by the return value of the function. When applied to a non-reference
216  parameter (for example, a pointer or a class type), all temporaries
217  referenced by the parameter are assumed to be retained by the return value of
218  the function.
219
220  See also the upstream documentation:
221  https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
222
223  This is a copy of ABSL_ATTRIBUTE_LIFETIME_BOUND.
224
225Modifying compiler diagnostics
226^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
227``pw_preprocessor/compiler.h`` provides macros for enabling or disabling
228compiler diagnostics (warnings or errors).
229
230.. c:macro:: PW_MODIFY_DIAGNOSTICS_PUSH()
231
232  Starts a new group of :c:macro:`PW_MODIFY_DIAGNOSTIC` statements. A
233  :c:macro:`PW_MODIFY_DIAGNOSTICS_POP` statement must follow.
234
235.. c:macro:: PW_MODIFY_DIAGNOSTICS_POP()
236
237  :c:macro:`PW_MODIFY_DIAGNOSTIC` statements since the most recent
238  :c:macro:`PW_MODIFY_DIAGNOSTICS_PUSH` no longer apply after this statement.
239
240.. c:macro:: PW_MODIFY_DIAGNOSTIC(kind, option)
241
242  Changes how a diagnostic (warning or error) is handled. Most commonly used to
243  disable warnings. ``PW_MODIFY_DIAGNOSTIC`` should be used between
244  :c:macro:`PW_MODIFY_DIAGNOSTICS_PUSH` and :c:macro:`PW_MODIFY_DIAGNOSTICS_POP`
245  statements to avoid applying the modifications too broadly.
246
247  ``kind`` may be ``warning``, ``error``, or ``ignored``.
248
249These macros can be used to disable warnings for precise sections of code, even
250a single line if necessary.
251
252.. code-block:: c
253
254  PW_MODIFY_DIAGNOSTICS_PUSH();
255  PW_MODIFY_DIAGNOSTIC(ignored, "-Wunused-variable");
256
257  static int this_variable_is_never_used;
258
259  PW_MODIFY_DIAGNOSTICS_POP();
260
261.. tip::
262
263  :c:macro:`PW_MODIFY_DIAGNOSTIC` and related macros should rarely be used.
264  Whenever possible, fix the underlying issues about which the compiler is
265  warning, rather than silencing the diagnostics.
266
267pw_preprocessor/concat.h
268------------------------
269Defines the ``PW_CONCAT(...)`` macro, which expands its arguments if they are
270macros and token pastes the results. This can be used for building names of
271classes, variables, macros, etc.
272
273pw_preprocessor/util.h
274----------------------
275General purpose, useful macros.
276
277* ``PW_ARRAY_SIZE(array)`` -- calculates the size of a C array
278* ``PW_STRINGIFY(...)`` -- expands its arguments as macros and converts them to
279  a string literal
280* ``PW_EXTERN_C`` -- declares a name to be ``extern "C"`` in C++; expands to
281  nothing in C
282* ``PW_EXTERN_C_START`` / ``PW_EXTERN_C_END`` -- declares an ``extern "C" { }``
283  block in C++; expands to nothing in C
284
285Zephyr
286======
287To enable ``pw_preprocessor`` for Zephyr add ``CONFIG_PIGWEED_PREPROCESSOR=y``
288to the project's configuration.
289