blob: 5a2b28e09234c4fd1c05dcaa924a906719b6f85b [file] [log] [blame]
Andrew Jeffery66c77232024-04-24 11:42:02 +09301/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2#ifndef PLDM_COMPILER_H
3#define PLDM_COMPILER_H
4
Andrew Jeffery3a2c6582024-11-07 16:30:36 +10305#include <libpldm/compiler.h>
6
Andrew Jeffery860a43d2024-08-23 01:21:58 +00007#ifndef __has_attribute
8#error The libpldm implementation requires __has_attribute
9#endif
10
11#include <assert.h>
12
13static struct {
Andrew Jefferycb569bc2024-09-01 09:38:09 +030014 static_assert(__has_attribute(always_inline),
15 "`always_inline` attribute is required");
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +030016 static_assert(__has_attribute(nonnull),
17 "`nonnull` attribute is required");
Andrew Jeffery860a43d2024-08-23 01:21:58 +000018 static_assert(__has_attribute(unused),
19 "`unused` attribute is required");
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +000020 static_assert(__has_attribute(warn_unused_result),
21 "`warn_unused_result` attribute is required");
Andrew Jefferya1896962025-03-03 21:41:25 +103022 static_assert(__has_attribute(cleanup),
23 "`cleanup` attribute is required");
Andrew Jeffery860a43d2024-08-23 01:21:58 +000024 int compliance;
25} pldm_required_attributes __attribute__((unused));
26
Andrew Jeffery3a2c6582024-11-07 16:30:36 +103027#ifndef LIBPLDM_CC_ALWAYS_INLINE
28#error Missing definition for LIBPLDM_ALWAYS_INLINE
29#endif
30
31#ifndef LIBPLDM_CC_NONNULL
32#error Missing definition for LIBPLDM_CC_NONNULL
33#endif
34
Andrew Jefferya1896962025-03-03 21:41:25 +103035#define LIBPLDM_CC_CLEANUP(fn) __attribute__((cleanup(fn)))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +030036#define LIBPLDM_CC_NONNULL_ARGS(...) __attribute__((nonnull(__VA_ARGS__)))
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +000037#define LIBPLDM_CC_UNUSED __attribute__((unused))
38#define LIBPLDM_CC_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
Andrew Jeffery860a43d2024-08-23 01:21:58 +000039
Andrew Jeffery66c77232024-04-24 11:42:02 +093040// NOLINTBEGIN(bugprone-macro-parentheses)
41/**
42 * Require that the given object is of the specified type.
43 *
44 * If the object is not of the required type then a diagnostic will be emitted.
45 *
46 * If you are reading this documentation due to hitting a compilation error
47 * passing through the macro, then you have a type error in your code that must
48 * be fixed. Despite the compiler output, the error is _not_ that some array
49 * is negatively sized, the array is negatively sized _because_ you have a type
50 * error.
51 *
52 * How this works:
53 *
54 * If the type of @p obj is not equivalent to the provided type @p type then
55 * we force the compiler to evaluate sizeof on a negatively-sized array. The
56 * C standard requires that the integer constant expression that specifies
57 * the array length must be greater than zero. Failure to meet this constraint
58 * generally terminates compilation of the translation unit as any other result
59 * cannot be handled in a sensible way. The array size is derived to an integer
60 * constant expression from a type eqivalence evaluated using _Generic()
61 * allowing us to stay within the language standard. The default generic
62 * association, representing a type mismatch, yields -1.
63 *
64 * pldm_require_obj_type() was introduced into the libpldm implementation to
65 * enable use of the pldm_msgbuf_extract*() APIs for objects that may or may not
66 * reside in a packed struct. See src/msgbuf.h for more details.
67 *
68 * @param obj The name of the object to evaluate
69 * @param type The required type of @p obj
70 *
71 * @return The expression either yields 1, or compilation is terminated
72 */
73#define pldm_require_obj_type(obj, type) \
74 ((void)(sizeof( \
75 struct { char buf[_Generic((obj), type: 1, default: -1)]; })))
76// NOLINTEND(bugprone-macro-parentheses)
77
78#endif