summaryrefslogtreecommitdiff
path: root/include/linux/stddef.h
blob: e1851c50c89b521437492c28b18c966e23fd08d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_STDDEF_H
#define _LINUX_STDDEF_H

#include <uapi/linux/stddef.h>

#undef NULL
#define NULL ((void *)0)

enum {
	false	= 0,
	true	= 1
};

#undef offsetof
#define offsetof(TYPE, MEMBER)	__builtin_offsetof(TYPE, MEMBER)

/**
 * sizeof_field() - Report the size of a struct field in bytes
 *
 * @TYPE: The structure containing the field of interest
 * @MEMBER: The field to return the size of
 */
#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))

/**
 * offsetofend() - Report the offset of a struct field within the struct
 *
 * @TYPE: The type of the structure
 * @MEMBER: The member within the structure to get the end offset of
 */
#define offsetofend(TYPE, MEMBER) \
	(offsetof(TYPE, MEMBER)	+ sizeof_field(TYPE, MEMBER))

/**
 * struct_group() - Wrap a set of declarations in a mirrored struct
 *
 * @NAME: The identifier name of the mirrored sub-struct
 * @MEMBERS: The member declarations for the mirrored structs
 *
 * Used to create an anonymous union of two structs with identical
 * layout and size: one anonymous and one named. The former can be
 * used normally without sub-struct naming, and the latter can be
 * used to reason about the start, end, and size of the group of
 * struct members.
 */
#define struct_group(NAME, MEMBERS...)	\
	__struct_group(/* no tag */, NAME, /* no attrs */, MEMBERS)

/**
 * struct_group_attr() - Create a struct_group() with trailing attributes
 *
 * @NAME: The identifier name of the mirrored sub-struct
 * @ATTRS: Any struct attributes to apply
 * @MEMBERS: The member declarations for the mirrored structs
 *
 * Used to create an anonymous union of two structs with identical
 * layout and size: one anonymous and one named. The former can be
 * used normally without sub-struct naming, and the latter can be
 * used to reason about the start, end, and size of the group of
 * struct members. Includes structure attributes argument.
 */
#define struct_group_attr(NAME, ATTRS, MEMBERS...) \
	__struct_group(/* no tag */, NAME, ATTRS, MEMBERS)

/**
 * struct_group_tagged() - Create a struct_group with a reusable tag
 *
 * @TAG: The tag name for the named sub-struct
 * @NAME: The identifier name of the mirrored sub-struct
 * @MEMBERS: The member declarations for the mirrored structs
 *
 * Used to create an anonymous union of two structs with identical
 * layout and size: one anonymous and one named. The former can be
 * used normally without sub-struct naming, and the latter can be
 * used to reason about the start, end, and size of the group of
 * struct members. Includes struct tag argument for the named copy,
 * so the specified layout can be reused later.
 */
#define struct_group_tagged(TAG, NAME, MEMBERS...) \
	__struct_group(TAG, NAME, /* no attrs */, MEMBERS)

/**
 * DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
 *
 * @TYPE: The type of each flexible array element
 * @NAME: The name of the flexible array member
 *
 * In order to have a flexible array member in a union or alone in a
 * struct, it needs to be wrapped in an anonymous struct with at least 1
 * named member, but that member can be empty.
 */
#define DECLARE_FLEX_ARRAY(TYPE, NAME) \
	__DECLARE_FLEX_ARRAY(TYPE, NAME)

/**
 * __TRAILING_OVERLAP() - Overlap a flexible-array member with trailing
 *			  members.
 *
 * Creates a union between a flexible-array member (FAM) in a struct and a set
 * of additional members that would otherwise follow it.
 *
 * Beware that, as this helper encloses TYPE NAME and MEMBERS in the same
 * union, designated initializers for MEMBERS may overwrite portions
 * previously initialized through NAME.
 *
 * For example::
 *
 *	struct flex {
 *		size_t count;
 *		u8 fam[];
 *	};
 *
 *	struct composite {
 *		...
 *		__TRAILING_OVERLAP(struct flex, flex, fam, __packed,
 *			u8 data;
 *		);
 *	} __packed;
 *
 *	static struct composite comp = {
 *		.flex = {
 *			.count = 1,
 *		},
 *		.data = 2,
 *	};
 *
 * In the example above, .flex and .data initialize different views of the same
 * union storage. Since .data is initialized last, it _may_ overwrite portions
 * previously initialized through .flex, leading to .flex.count being zeroed
 * out.
 *
 * A couple of alternatives are shown below.
 *
 * a) Initialize only one view of the overlapped storage and assign the rest
 *    at runtime::
 *
 *	static struct composite comp = {
 *		.flex = {
 *			.count = 1,
 *		},
 *	};
 *
 *	static void foo(void)
 *	{
 *		comp.data = 2;
 *		...
 *	}
 *
 * b) Alternatively, replace designated initializers with runtime assignments::
 *
 *	static void foo(void)
 *	{
 *		struct composite comp;
 *
 *		comp.flex.count = 1;
 *		comp.data = 2;
 *		...
 *	}
 *
 * Compiler Explorer test code: https://godbolt.org/z/voM4E36dT
 *
 * For another example of the above see commit 5e54510a9389 ("acpi: nfit:
 * intel: avoid multiple -Wflex-array-member-not-at-end warnings")
 *
 * Link: https://git.kernel.org/linus/5e54510a9389caa9
 *
 * @TYPE: Flexible structure type name, including "struct" keyword.
 * @NAME: Name for a variable to define.
 * @FAM: The flexible-array member within @TYPE
 * @ATTRS: Any struct attributes (usually empty)
 * @MEMBERS: Trailing overlapping members.
 */
#define __TRAILING_OVERLAP(TYPE, NAME, FAM, ATTRS, MEMBERS)			\
	union {									\
		TYPE NAME;							\
		struct {							\
			unsigned char __offset_to_FAM[offsetof(TYPE, FAM)];	\
			MEMBERS							\
		} ATTRS;							\
	}

/**
 * TRAILING_OVERLAP() - Overlap a flexible-array member with trailing members.
 *
 * Creates a union between a flexible-array member (FAM) in a struct and a set
 * of additional members that would otherwise follow it.
 *
 * @TYPE: Flexible structure type name, including "struct" keyword.
 * @NAME: Name for a variable to define.
 * @FAM: The flexible-array member within @TYPE
 * @MEMBERS: Trailing overlapping members.
 */
#define TRAILING_OVERLAP(TYPE, NAME, FAM, MEMBERS)				\
	__TRAILING_OVERLAP(TYPE, NAME, FAM, /* no attrs */, MEMBERS)

#endif