diff options
Diffstat (limited to 'lib/must_be.h')
-rw-r--r-- | lib/must_be.h | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/must_be.h b/lib/must_be.h new file mode 100644 index 0000000..a7365cb --- /dev/null +++ b/lib/must_be.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2019-2023, Alejandro Colomar <alx@kernel.org> + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef SHADOW_INCLUDE_LIBMISC_MUST_BE_H_ +#define SHADOW_INCLUDE_LIBMISC_MUST_BE_H_ + + +#include <config.h> + +#include <assert.h> + + +/* + * SYNOPSIS + * int must_be(bool e); + * + * ARGUMENTS + * e Expression to be asserted. + * + * DESCRIPTION + * This macro fails compilation if 'e' is false. If 'e' is true, + * it returns (int) 0, so it doesn't affect the expression in which + * it is contained. + * + * This macro is similar to static_assert(3). While + * static_assert(3) can only be used where a statement is allowed, + * this must_be() macro can be used wherever an expression is + * allowed. + * + * RETURN VALUE + * 0 + * + * ERRORS + * If 'e' is false, the compilation will fail, as when using + * static_assert(3). + * + * EXAMPLES + * #define must_be_array(a) must_be(is_array(a)) + * + * #define NITEMS(a) (sizeof(a) / sizeof(*(a)) + must_be_array(a)) + * + * int foo[42]; + * int bar[NITEMS(foo)]; + */ + + +#define must_be(e) \ +( \ + 0 * (int) sizeof( \ + struct { \ + static_assert(e, ""); \ + int ISO_C_forbids_a_struct_with_no_members_; \ + } \ + ) \ +) + + +/* + * SYNOPSIS + * int must_be_array(a); + * + * ARGUMENTS + * a Array. + * + * DESCRIPTION + * This macro fails compilation if 'a' is not an array. It is + * useful in macros that accept an array as a parameter, where this + * macro can validate the macro argument. It prevent passing a + * pointer to such macros, which would otherwise produce silent + * bugs. + * + * RETURN VALUE + * 0 + * + * ERRORS + * If 'a' is not an array, the compilation will fail. + * + * EXAMPLES + * int a[10]; + * int *p; + * + * must_be_array(a); // Ok + * must_be_array(p); // Compile-time error + * + * SEE ALSO + * must_be() + */ + + +#define is_same_type(a, b) __builtin_types_compatible_p(a, b) +#define is_same_typeof(a, b) is_same_type(typeof(a), typeof(b)) +#define is_array(a) (!is_same_typeof((a), &(a)[0])) +#define must_be_array(a) must_be(is_array(a)) + + +#endif // include guard |