1 /* CC0 (Public domain) - see LICENSE file for details */
7 * TCON - declare a _tcon type containing canary variables.
8 * @decls: the semi-colon separated list of type canaries.
10 * This declares a _tcon member for a structure. It should be the
11 * last element in your structure; with sufficient compiler support it
12 * will not use any actual storage. tcon_check() will compare
13 * expressions with one of these "type canaries" to cause warnings if
14 * the container is misused.
16 * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
19 * // Simply typesafe linked list.
21 * struct list_head *prev, *next;
24 * struct string_list {
25 * struct list_head raw;
29 * // More complex: mapping from one type to another.
34 * struct int_to_string_map {
36 * TCON(char *charp_canary; int int_canary);
39 #if HAVE_FLEXIBLE_ARRAY_MEMBER
40 #define TCON(decls) struct { decls; } _tcon[]
42 #define TCON(decls) struct { decls; } _tcon[1]
46 * TCON_WRAP - declare a wrapper type containing a base type and type canaries
47 * @basetype: the base type to wrap
48 * @decls: the semi-colon separated list of type canaries.
50 * This expands to a new type which includes the given base type, and
51 * also type canaries, similar to those created with TCON.
53 * The embedded base type value can be accessed using tcon_unwrap().
55 * Differences from using TCON()
56 * - The wrapper type will take either the size of the base type, or
57 * the size of a single pointer, whichever is greater (regardless of
59 * - A TCON_WRAP type may be included in another structure, and need
60 * not be the last element.
62 * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
65 * // Simply typesafe linked list.
67 * struct list_head *prev, *next;
70 * typedef TCON_WRAP(struct list_head, char *canary) string_list_t;
72 * // More complex: mapping from one type to another.
77 * typedef TCON_WRAP(struct map, char *charp_canary; int int_canary)
78 * int_to_string_map_t;
80 #define TCON_WRAP(basetype, decls) \
89 * TCON_WRAP_INIT - an initializer for a variable declared with TCON_WRAP
90 * @...: Initializer for the base type (treated as variadic so commas
93 * Converts converts an initializer suitable for a base type into one
94 * suitable for that type wrapped with TCON_WRAP.
97 * TCON_WRAP(int, char *canary) canaried_int = TCON_WRAP_INIT(17);
99 #define TCON_WRAP_INIT(...) \
100 { ._base = __VA_ARGS__, }
103 * tcon_unwrap - Access the base type of a TCON_WRAP
104 * @ptr: pointer to an object declared with TCON_WRAP
106 * tcon_unwrap() returns a pointer to the base type of the TCON_WRAP()
107 * object pointer to by @ptr.
110 * TCON_WRAP(int, char *canary) canaried_int;
112 * *tcon_unwrap(&canaried_int) = 17;
114 #define tcon_unwrap(ptr) (&((ptr)->_base))
117 * tcon_check - typecheck a typed container
118 * @x: the structure containing the TCON.
119 * @canary: which canary to check against.
120 * @expr: the expression whose type must match the TCON (not evaluated)
122 * This macro is used to check that the expression is the type
123 * expected for this structure (note the "useless" sizeof() argument
124 * which contains this comparison with the type canary).
126 * It evaluates to @x so you can chain it.
129 * #define tlist_add(h, n, member) \
130 * list_add(&tcon_check((h), canary, (n))->raw, &(n)->member)
132 #define tcon_check(x, canary, expr) \
133 (sizeof((x)->_tcon[0].canary == (expr)) ? (x) : (x))
136 * tcon_check_ptr - typecheck a typed container
137 * @x: the structure containing the TCON.
138 * @canary: which canary to check against.
139 * @expr: the expression whose type must match &TCON (not evaluated)
141 * This macro is used to check that the expression is a pointer to the type
142 * expected for this structure (note the "useless" sizeof() argument
143 * which contains this comparison with the type canary), or NULL.
145 * It evaluates to @x so you can chain it.
147 #define tcon_check_ptr(x, canary, expr) \
148 (sizeof(&(x)->_tcon[0].canary == (expr)) ? (x) : (x))
152 * tcon_type - the type within a container (or void *)
153 * @x: the structure containing the TCON.
154 * @canary: which canary to check against.
157 #define tcon_type(x, canary) __typeof__((x)->_tcon[0].canary)
159 #define tcon_type(x, canary) void *
163 * tcon_sizeof - the size of type within a container
164 * @x: the structure containing the TCON.
165 * @canary: which canary to check against.
167 #define tcon_sizeof(x, canary) sizeof((x)->_tcon[0].canary)
170 * tcon_ptr_type - pointer to the type within a container (or void *)
171 * @x: the structure containing the TCON.
172 * @canary: which canary to check against.
175 #define tcon_ptr_type(x, canary) __typeof__(&(x)->_tcon[0].canary)
177 #define tcon_ptr_type(x, canary) void *
181 * tcon_cast - cast to a canary type for this container (or void *)
182 * @x: a structure containing the TCON.
183 * @canary: which canary to cast to.
184 * @expr: the value to cast
186 * This is used to cast to the correct type for this container. If the
187 * platform doesn't HAVE_TYPEOF, then it casts to void * (which will
188 * cause a warning if the user doesn't expect a pointer type).
190 #define tcon_cast(x, canary, expr) ((tcon_type((x), canary))(expr))
191 #define tcon_cast_ptr(x, canary, expr) ((tcon_ptr_type((x), canary))(expr))
193 #endif /* CCAN_TCON_H */