289 lines
9.5 KiB
ReStructuredText
289 lines
9.5 KiB
ReStructuredText
.. _module-pw_preprocessor:
|
|
|
|
---------------
|
|
pw_preprocessor
|
|
---------------
|
|
The preprocessor module provides various helpful preprocessor macros.
|
|
|
|
Compatibility
|
|
=============
|
|
C and C++
|
|
|
|
Headers
|
|
=======
|
|
The preprocessor module provides several headers.
|
|
|
|
pw_preprocessor/arguments.h
|
|
---------------------------------
|
|
Defines macros for handling variadic arguments to function-like macros. Macros
|
|
include the following:
|
|
|
|
.. c:macro:: PW_DELEGATE_BY_ARG_COUNT(name, ...)
|
|
|
|
Selects and invokes a macro based on the number of arguments provided. Expands
|
|
to ``<name><arg_count>(...)``. For example,
|
|
``PW_DELEGATE_BY_ARG_COUNT(foo_, 1, 2, 3)`` expands to ``foo_3(1, 2, 3)``.
|
|
|
|
This example shows how ``PW_DELEGATE_BY_ARG_COUNT`` could be used to log a
|
|
customized message based on the number of arguments provided.
|
|
|
|
.. code-block:: cpp
|
|
|
|
#define ARG_PRINT(...) PW_DELEGATE_BY_ARG_COUNT(_ARG_PRINT, __VA_ARGS__)
|
|
#define _ARG_PRINT0(a) LOG_INFO("nothing!")
|
|
#define _ARG_PRINT1(a) LOG_INFO("1 arg: %s", a)
|
|
#define _ARG_PRINT2(a, b) LOG_INFO("2 args: %s, %s", a, b)
|
|
#define _ARG_PRINT3(a, b, c) LOG_INFO("3 args: %s, %s, %s", a, b, c)
|
|
|
|
When used, ``ARG_PRINT`` expands to the ``_ARG_PRINT#`` macro corresponding
|
|
to the number of arguments.
|
|
|
|
.. code-block:: cpp
|
|
|
|
ARG_PRINT(); // Outputs: nothing!
|
|
ARG_PRINT("a"); // Outputs: 1 arg: a
|
|
ARG_PRINT("a", "b"); // Outputs: 2 args: a, b
|
|
ARG_PRINT("a", "b", "c"); // Outputs: 3 args: a, b, c
|
|
|
|
.. c:macro:: PW_COMMA_ARGS(...)
|
|
|
|
Expands to a comma followed by the arguments if any arguments are provided.
|
|
Otherwise, expands to nothing. If the final argument is empty, it is omitted.
|
|
This is useful when passing ``__VA_ARGS__`` to a variadic function or template
|
|
parameter list, since it removes the extra comma when no arguments are
|
|
provided. ``PW_COMMA_ARGS`` must NOT be used when invoking a macro from
|
|
another macro.
|
|
|
|
For example. ``PW_COMMA_ARGS(1, 2, 3)``, expands to ``, 1, 2, 3``, while
|
|
``PW_COMMA_ARGS()`` expands to nothing. ``PW_COMMA_ARGS(1, 2, )`` expands to
|
|
``, 1, 2``.
|
|
|
|
pw_preprocessor/boolean.h
|
|
-------------------------
|
|
Defines macros for boolean logic on literal 1s and 0s. This is useful for
|
|
situations when a literal is needed to build the name of a function or macro.
|
|
|
|
pw_preprocessor/compiler.h
|
|
--------------------------
|
|
Macros for compiler-specific features, such as attributes or builtins.
|
|
|
|
.. c:macro:: PW_PACKED(declaration)
|
|
|
|
Marks a struct or class as packed.
|
|
|
|
.. c:macro:: PW_USED
|
|
|
|
Marks a function or object as used, ensuring code for it is generated.
|
|
|
|
.. c:macro:: PW_NO_PROLOGUE
|
|
|
|
Prevents generation of a prologue or epilogue for a function. This is
|
|
helpful when implementing the function in assembly.
|
|
|
|
.. c:macro:: PW_PRINTF_FORMAT(format_index, parameter_index)
|
|
|
|
Marks that a function declaration takes a printf-style format string and
|
|
variadic arguments. This allows the compiler to perform check the validity of
|
|
the format string and arguments. This macro must only be on the function
|
|
declaration, not the definition.
|
|
|
|
The format_index is index of the format string parameter and parameter_index
|
|
is the starting index of the variadic arguments. Indices start at 1. For C++
|
|
class member functions, add one to the index to account for the implicit this
|
|
parameter.
|
|
|
|
This example shows a function where the format string is argument 2 and the
|
|
varargs start at argument 3.
|
|
|
|
.. code-block:: cpp
|
|
|
|
int PrintfStyleFunction(char* buffer,
|
|
const char* fmt, ...) PW_PRINTF_FORMAT(2,3);
|
|
|
|
int PrintfStyleFunction(char* buffer, const char* fmt, ...) {
|
|
... implementation here ...
|
|
}
|
|
|
|
.. c:macro:: PW_PLACE_IN_SECTION(name)
|
|
|
|
Places a variable in the specified linker section.
|
|
|
|
.. c:macro:: PW_KEEP_IN_SECTION(name)
|
|
|
|
Places a variable in the specified linker section and directs the compiler
|
|
to keep the variable, even if it is not used. Depending on the linker
|
|
options, the linker may still remove this section if it is not declared in
|
|
the linker script and marked KEEP.
|
|
|
|
.. c:macro:: PW_NO_RETURN
|
|
|
|
Indicate to the compiler that the annotated function won't return. Example:
|
|
|
|
.. code-block:: cpp
|
|
|
|
PW_NO_RETURN void HandleAssertFailure(ErrorCode error_code);
|
|
|
|
|
|
.. c:macro:: PW_NO_INLINE
|
|
|
|
Prevents the compiler from inlining a fuction.
|
|
|
|
.. c:macro:: PW_UNREACHABLE
|
|
|
|
Indicate to the compiler that the given section of code will not be reached.
|
|
Example:
|
|
|
|
.. code-block:: cpp
|
|
|
|
int main() {
|
|
InitializeBoard();
|
|
vendor_StartScheduler(); // Note: vendor forgot noreturn attribute.
|
|
PW_UNREACHABLE;
|
|
}
|
|
|
|
|
|
.. c:macro:: PW_NO_SANITIZE(check)
|
|
|
|
Indicate to a sanitizer compiler runtime to skip the named check in the
|
|
associated function.
|
|
Example:
|
|
|
|
.. code-block:: cpp
|
|
|
|
uint32_t djb2(const void* buf, size_t len)
|
|
PW_NO_SANITIZE("unsigned-integer-overflow"){
|
|
uint32_t hash = 5381;
|
|
const uint8_t* u8 = static_cast<const uint8_t*>(buf);
|
|
for (size_t i = 0; i < len; ++i) {
|
|
hash = (hash * 33) + u8[i]; // hash * 33 + c
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
.. c:macro:: PW_HAVE_ATTRIBUTE(x)
|
|
|
|
Wrapper around `__has_attribute`, which is defined by GCC 5+ and Clang and
|
|
evaluates to a non zero constant integer if the attribute is supported or 0
|
|
if not.
|
|
|
|
.. c:macro:: PW_HAVE_CPP_ATTRIBUTE(x)
|
|
|
|
Wrapper around `__has_cpp_attribute`, which was introduced in the C++20
|
|
standard. It is supported by compilers even if C++20 is not in use. Evaluates
|
|
to a non zero constant integer if the C++ attribute is supported or 0 if not.
|
|
|
|
.. c:macro:: PW_PRAGMA(contents)
|
|
|
|
Expands to a _Pragma with the contents as a string. _Pragma must take a
|
|
single string literal; this can be used to construct a _Pragma argument.
|
|
|
|
.. c:macro:: PW_WEAK
|
|
|
|
Marks a function or object as weak, allowing the definition to be overriden.
|
|
|
|
This can be useful when supporting third-party SDKs which may conditionally
|
|
compile in code, for example:
|
|
|
|
.. code-block:: cpp
|
|
|
|
PW_WEAK void SysTick_Handler(void) {
|
|
// Default interrupt handler that might be overriden.
|
|
}
|
|
|
|
.. c:macro:: PW_ALIAS(aliased_to)
|
|
|
|
Marks a weak function as an alias to another, allowing the definition to
|
|
be given a default and overriden.
|
|
|
|
This can be useful when supporting third-party SDKs which may conditionally
|
|
compile in code, for example:
|
|
|
|
.. code-block:: cpp
|
|
|
|
// Driver handler replaced with default unless overridden.
|
|
void USART_DriverHandler(void) PW_ALIAS(DefaultDriverHandler);
|
|
|
|
.. c:macro:: PW_ATTRIBUTE_LIFETIME_BOUND
|
|
|
|
PW_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
|
|
parameter or implicit object parameter is retained by the return value of the
|
|
annotated function (or, for a parameter of a constructor, in the value of the
|
|
constructed object). This attribute causes warnings to be produced if a
|
|
temporary object does not live long enough.
|
|
|
|
When applied to a reference parameter, the referenced object is assumed to be
|
|
retained by the return value of the function. When applied to a non-reference
|
|
parameter (for example, a pointer or a class type), all temporaries
|
|
referenced by the parameter are assumed to be retained by the return value of
|
|
the function.
|
|
|
|
See also the upstream documentation:
|
|
https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
|
|
|
|
This is a copy of ABSL_ATTRIBUTE_LIFETIME_BOUND.
|
|
|
|
Modifying compiler diagnostics
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
``pw_preprocessor/compiler.h`` provides macros for enabling or disabling
|
|
compiler diagnostics (warnings or errors).
|
|
|
|
.. c:macro:: PW_MODIFY_DIAGNOSTICS_PUSH()
|
|
|
|
Starts a new group of :c:macro:`PW_MODIFY_DIAGNOSTIC` statements. A
|
|
:c:macro:`PW_MODIFY_DIAGNOSTICS_POP` statement must follow.
|
|
|
|
.. c:macro:: PW_MODIFY_DIAGNOSTICS_POP()
|
|
|
|
:c:macro:`PW_MODIFY_DIAGNOSTIC` statements since the most recent
|
|
:c:macro:`PW_MODIFY_DIAGNOSTICS_PUSH` no longer apply after this statement.
|
|
|
|
.. c:macro:: PW_MODIFY_DIAGNOSTIC(kind, option)
|
|
|
|
Changes how a diagnostic (warning or error) is handled. Most commonly used to
|
|
disable warnings. ``PW_MODIFY_DIAGNOSTIC`` should be used between
|
|
:c:macro:`PW_MODIFY_DIAGNOSTICS_PUSH` and :c:macro:`PW_MODIFY_DIAGNOSTICS_POP`
|
|
statements to avoid applying the modifications too broadly.
|
|
|
|
``kind`` may be ``warning``, ``error``, or ``ignored``.
|
|
|
|
These macros can be used to disable warnings for precise sections of code, even
|
|
a single line if necessary.
|
|
|
|
.. code-block:: c
|
|
|
|
PW_MODIFY_DIAGNOSTICS_PUSH();
|
|
PW_MODIFY_DIAGNOSTIC(ignored, "-Wunused-variable");
|
|
|
|
static int this_variable_is_never_used;
|
|
|
|
PW_MODIFY_DIAGNOSTICS_POP();
|
|
|
|
.. tip::
|
|
|
|
:c:macro:`PW_MODIFY_DIAGNOSTIC` and related macros should rarely be used.
|
|
Whenever possible, fix the underlying issues about which the compiler is
|
|
warning, rather than silencing the diagnostics.
|
|
|
|
pw_preprocessor/concat.h
|
|
------------------------
|
|
Defines the ``PW_CONCAT(...)`` macro, which expands its arguments if they are
|
|
macros and token pastes the results. This can be used for building names of
|
|
classes, variables, macros, etc.
|
|
|
|
pw_preprocessor/util.h
|
|
----------------------
|
|
General purpose, useful macros.
|
|
|
|
* ``PW_ARRAY_SIZE(array)`` -- calculates the size of a C array
|
|
* ``PW_STRINGIFY(...)`` -- expands its arguments as macros and converts them to
|
|
a string literal
|
|
* ``PW_EXTERN_C`` -- declares a name to be ``extern "C"`` in C++; expands to
|
|
nothing in C
|
|
* ``PW_EXTERN_C_START`` / ``PW_EXTERN_C_END`` -- declares an ``extern "C" { }``
|
|
block in C++; expands to nothing in C
|
|
|
|
Zephyr
|
|
======
|
|
To enable ``pw_preprocessor`` for Zephyr add ``CONFIG_PIGWEED_PREPROCESSOR=y``
|
|
to the project's configuration.
|