xref: /xnu-8796.101.5/bsd/sys/constrained_ctypes.h (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions  * Copyright (c) 2000-2022 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions  *
4*aca3beaaSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions  *
6*aca3beaaSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*aca3beaaSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*aca3beaaSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*aca3beaaSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*aca3beaaSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*aca3beaaSApple OSS Distributions  *
15*aca3beaaSApple OSS Distributions  * Please obtain a copy of the License at
16*aca3beaaSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*aca3beaaSApple OSS Distributions  *
18*aca3beaaSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*aca3beaaSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*aca3beaaSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*aca3beaaSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*aca3beaaSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*aca3beaaSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*aca3beaaSApple OSS Distributions  * limitations under the License.
25*aca3beaaSApple OSS Distributions  *
26*aca3beaaSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*aca3beaaSApple OSS Distributions  */
28*aca3beaaSApple OSS Distributions 
29*aca3beaaSApple OSS Distributions #ifndef __CONSTRAINED_CTYPES__
30*aca3beaaSApple OSS Distributions #define __CONSTRAINED_CTYPES__
31*aca3beaaSApple OSS Distributions 
32*aca3beaaSApple OSS Distributions #include <sys/cdefs.h>
33*aca3beaaSApple OSS Distributions 
34*aca3beaaSApple OSS Distributions /*
35*aca3beaaSApple OSS Distributions  * Constraining pointer types based on contracts.
36*aca3beaaSApple OSS Distributions  *
37*aca3beaaSApple OSS Distributions  * 1. List of supported constrained pointers.
38*aca3beaaSApple OSS Distributions  *
39*aca3beaaSApple OSS Distributions  * 1.1. `Reference' pointers.
40*aca3beaaSApple OSS Distributions  *
41*aca3beaaSApple OSS Distributions  *      The `reference' pointers point to a single entity. The pointer
42*aca3beaaSApple OSS Distributions  *      arithmetics are not supported for the `reference' pointers.
43*aca3beaaSApple OSS Distributions  *
44*aca3beaaSApple OSS Distributions  *      The `reference' pointers are fully ABI compatible with
45*aca3beaaSApple OSS Distributions  *      the unconstrained C pointers.
46*aca3beaaSApple OSS Distributions  *
47*aca3beaaSApple OSS Distributions  *      The naming convention for the `reference' pointers uses
48*aca3beaaSApple OSS Distributions  *      the `ref' constraint tag. See `Naming conventions' below for furhter
49*aca3beaaSApple OSS Distributions  *      discussion.
50*aca3beaaSApple OSS Distributions  *
51*aca3beaaSApple OSS Distributions  *      Examples:
52*aca3beaaSApple OSS Distributions  *
53*aca3beaaSApple OSS Distributions  *      (1) `socket_ref_t' is `reference' pointer to `struct socket'.
54*aca3beaaSApple OSS Distributions  *      (2) `uint32_ref_t' is `reference' pointer to `uint32_t'.
55*aca3beaaSApple OSS Distributions  *
56*aca3beaaSApple OSS Distributions  *
57*aca3beaaSApple OSS Distributions  * 1.2. `Checked' pointers.
58*aca3beaaSApple OSS Distributions  *
59*aca3beaaSApple OSS Distributions  *      The `checked' pointers represent contigous data arrays, which
60*aca3beaaSApple OSS Distributions  *      can be traversed only in the direction of increasing memory addresses.
61*aca3beaaSApple OSS Distributions  *      The pointer arithmetics are partially supported: decrements (p--, --p)
62*aca3beaaSApple OSS Distributions  *      are disallowed.
63*aca3beaaSApple OSS Distributions  *
64*aca3beaaSApple OSS Distributions  *      The `checked' pointers are not ABI-compatible with plain C pointers,
65*aca3beaaSApple OSS Distributions  *      due to the boundary checks instrumentation. See `ABI
66*aca3beaaSApple OSS Distributions  *      Compatibility Considerations' below for further discussion.
67*aca3beaaSApple OSS Distributions  *
68*aca3beaaSApple OSS Distributions  *      The naming convention for the `checked' pointers uses the `ptr'
69*aca3beaaSApple OSS Distributions  *      constraint tag. See `Naming conventions' below for furhter discussion.
70*aca3beaaSApple OSS Distributions  *
71*aca3beaaSApple OSS Distributions  *      Examples:
72*aca3beaaSApple OSS Distributions  *
73*aca3beaaSApple OSS Distributions  *      (1) `socket_ptr_t' is `checked' pointer to `struct socket'.
74*aca3beaaSApple OSS Distributions  *      (2) `uint32_ptr_t' is `checked' pointer to `uint32_t'.
75*aca3beaaSApple OSS Distributions  *
76*aca3beaaSApple OSS Distributions  *
77*aca3beaaSApple OSS Distributions  * 1.3. `Bidirectional' pointers.
78*aca3beaaSApple OSS Distributions  *
79*aca3beaaSApple OSS Distributions  *      The `bidirectional' pointers represent contigous data arrays,
80*aca3beaaSApple OSS Distributions  *      which can be traversed in both directions. The pointer arithmetics are
81*aca3beaaSApple OSS Distributions  *      fully supported for the `array' pointers.
82*aca3beaaSApple OSS Distributions  *
83*aca3beaaSApple OSS Distributions  *      The `bidirectional' pointers are not ABI-compatible with plain C
84*aca3beaaSApple OSS Distributions  *      pointers, due to the boundary checks instrumentation. Additionally,
85*aca3beaaSApple OSS Distributions  *      passing `bidirectional' pointers to functions require the use of stack.
86*aca3beaaSApple OSS Distributions  *      See `ABI Compatibility Considerations' below for further discussion.
87*aca3beaaSApple OSS Distributions  *
88*aca3beaaSApple OSS Distributions  *      The naming convention for the `bidirectional' pointers uses
89*aca3beaaSApple OSS Distributions  *      the `bptr' constraint tag. See `Naming conventions' below for furhter
90*aca3beaaSApple OSS Distributions  *      discussion.
91*aca3beaaSApple OSS Distributions  *
92*aca3beaaSApple OSS Distributions  *      Examples:
93*aca3beaaSApple OSS Distributions  *
94*aca3beaaSApple OSS Distributions  *      (1) `socket_bptr_t' is `bidirectional' pointer to `struct socket'.
95*aca3beaaSApple OSS Distributions  *      (2) `uint32_bptr_t' is `bidirectional' pointer to `uint32_t'.
96*aca3beaaSApple OSS Distributions  *
97*aca3beaaSApple OSS Distributions  *
98*aca3beaaSApple OSS Distributions  * 1.4. Multidimensional constrained pointers.
99*aca3beaaSApple OSS Distributions  *
100*aca3beaaSApple OSS Distributions  *      Constraining multidimensional pointers is achieved by iteratively
101*aca3beaaSApple OSS Distributions  *      applying the constraints from the innermost type to the outermost type.
102*aca3beaaSApple OSS Distributions  *
103*aca3beaaSApple OSS Distributions  *      Pointer arithmetics are supported for the dimensions that
104*aca3beaaSApple OSS Distributions  *      are not constrained to a `reference' or `const reference'.
105*aca3beaaSApple OSS Distributions  *
106*aca3beaaSApple OSS Distributions  *      If any of the dimension constraints isn't ABI-compatible with its
107*aca3beaaSApple OSS Distributions  *      unconstrained counterpart, then the entire constrained multidimensional
108*aca3beaaSApple OSS Distributions  *      pointer is not ABI-compatible with the corresponding unconstrained
109*aca3beaaSApple OSS Distributions  *      multidimensional pointer. Otherwise, the two are ABI-compatible. See
110*aca3beaaSApple OSS Distributions  *      `ABI compatibility' below for further discussion.
111*aca3beaaSApple OSS Distributions  *
112*aca3beaaSApple OSS Distributions  *      The naming convention for the multidimensional constrained pointers
113*aca3beaaSApple OSS Distributions  *      combines the naming tags that correspond to the individual constraints.
114*aca3beaaSApple OSS Distributions  *      See `Naming conventions' below for furhter discussion.
115*aca3beaaSApple OSS Distributions  *
116*aca3beaaSApple OSS Distributions  *      Examples:
117*aca3beaaSApple OSS Distributions  *
118*aca3beaaSApple OSS Distributions  *      (1) `socket_ref_bptr_t' is a `bidirectional' pointer to a `reference'
119*aca3beaaSApple OSS Distributions  *          pointer to `struct socket'.
120*aca3beaaSApple OSS Distributions  *      (2) `socket_ptr_ref_t' is a `reference' pointer to a `checked'
121*aca3beaaSApple OSS Distributions  *          pointer to `struct socket'.
122*aca3beaaSApple OSS Distributions  *
123*aca3beaaSApple OSS Distributions  *
124*aca3beaaSApple OSS Distributions  * 1.5. Using `const', `volatile', and `restrict' type qualifiers with
125*aca3beaaSApple OSS Distributions  *      constrained types.
126*aca3beaaSApple OSS Distributions  *
127*aca3beaaSApple OSS Distributions  *      The use of the `const', `volatile', and `restrict' type qualifiers
128*aca3beaaSApple OSS Distributions  *      (a.k.a. "CRV qualifiers") follows the syntax of the C language.
129*aca3beaaSApple OSS Distributions  *
130*aca3beaaSApple OSS Distributions  *      As a special case, if a `const' qualifier is applied to inner
131*aca3beaaSApple OSS Distributions  *      dimensions of a multidimensional constrained pointer type, the
132*aca3beaaSApple OSS Distributions  *      constraint tag is prepended with letter `c'; thus `cref' can be used
133*aca3beaaSApple OSS Distributions  *      for const-qualified `reference' pointer. This abbreviation is only
134*aca3beaaSApple OSS Distributions  *      supported for the `const' qualifier, as use of `volatile' or `restrict'
135*aca3beaaSApple OSS Distributions  *      for inner constrained types is quite uncommon. See `Multidimensional
136*aca3beaaSApple OSS Distributions  *      constrained pointers' above and `Naming conventions' below for further
137*aca3beaaSApple OSS Distributions  *      discussion.
138*aca3beaaSApple OSS Distributions  *
139*aca3beaaSApple OSS Distributions  *      Examples:
140*aca3beaaSApple OSS Distributions  *
141*aca3beaaSApple OSS Distributions  *      (1) `socket_ref_t const' is the const-qualified `reference' pointer
142*aca3beaaSApple OSS Distributions  *          to `struct socket'.
143*aca3beaaSApple OSS Distributions  *      (2) `socket_ptr_t volatile' is the volatile-qualified `checked' pointer
144*aca3beaaSApple OSS Distributions  *          to `struct socket'.
145*aca3beaaSApple OSS Distributions  *      (3) `socket_ptr_ref_t const' is a const-qualified `reference' pointer
146*aca3beaaSApple OSS Distributions  *          to a `checked' pointer to `struct socket'.
147*aca3beaaSApple OSS Distributions  *      (4) `socket_cref_ptr_t const' is a `checked' pointer to a
148*aca3beaaSApple OSS Distributions  *          const-qualified `reference' pointer to `struct socket'.
149*aca3beaaSApple OSS Distributions  *
150*aca3beaaSApple OSS Distributions  *
151*aca3beaaSApple OSS Distributions  * 1.6. Combining constrained pointers and unconstrained pointers.
152*aca3beaaSApple OSS Distributions  *
153*aca3beaaSApple OSS Distributions  *      Unconstrained pointers to constrained pointers follow
154*aca3beaaSApple OSS Distributions  *      the standard C syntax. Defining constrained pointers to
155*aca3beaaSApple OSS Distributions  *      unconstrained pointers is possible via defining a constrained pointer
156*aca3beaaSApple OSS Distributions  *      to a typedef.
157*aca3beaaSApple OSS Distributions  *
158*aca3beaaSApple OSS Distributions  *      Examples:
159*aca3beaaSApple OSS Distributions  *
160*aca3beaaSApple OSS Distributions  *      (1) `socket_ref_t *' is an unconstrained pointer to `socket_ref_t', i.e.
161*aca3beaaSApple OSS Distributions  *          unconstrained pointer to a `reference' pointer to `struct socket'.
162*aca3beaaSApple OSS Distributions  *      (2) `socket_ref_t const *' is an unconstrained pointer to `socket_ref_t const',
163*aca3beaaSApple OSS Distributions  *          i.e. an unconstrained pointer to a const-qualified `reference'
164*aca3beaaSApple OSS Distributions  *          pointer to `struct socket'.
165*aca3beaaSApple OSS Distributions  *      (3) `socket_ref_t * const' is a const-qualified unconstrained pointer to
166*aca3beaaSApple OSS Distributions  *          `socket_ref_t', i.e. a const-qualified unconstrained pointer to a
167*aca3beaaSApple OSS Distributions  *          `reference' pointer to `struct socket'.
168*aca3beaaSApple OSS Distributions  *      (4) `intptr_ref_t' is a `reference' pointer to `intptr_t', i.e.
169*aca3beaaSApple OSS Distributions  *          a `reference' pointer to an unconstrained pointer to `int'. Note
170*aca3beaaSApple OSS Distributions  *          the use of `intptr_t' typedef, which is necessary at the moment.
171*aca3beaaSApple OSS Distributions  *
172*aca3beaaSApple OSS Distributions  *
173*aca3beaaSApple OSS Distributions  * 2. Defining constrained pointer types.
174*aca3beaaSApple OSS Distributions  *
175*aca3beaaSApple OSS Distributions  * 2.1. Declaring multiple constrained types simultaneously.
176*aca3beaaSApple OSS Distributions  *
177*aca3beaaSApple OSS Distributions  *      `__CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)`
178*aca3beaaSApple OSS Distributions  *      is the suggested way to declare constrained pointer types.
179*aca3beaaSApple OSS Distributions  *
180*aca3beaaSApple OSS Distributions  *      Parameters:
181*aca3beaaSApple OSS Distributions  *
182*aca3beaaSApple OSS Distributions  *      `basetype`: the pointee type, including `struct' or `enum' keywords.
183*aca3beaaSApple OSS Distributions  *      `basetag`:  the prefix of the constrained type.
184*aca3beaaSApple OSS Distributions  *
185*aca3beaaSApple OSS Distributions  *      This macro acts differently in the user-space and the kernel-space
186*aca3beaaSApple OSS Distributions  *      code.
187*aca3beaaSApple OSS Distributions  *      When used in the user-space code, the macro will declare
188*aca3beaaSApple OSS Distributions  *      types which are ABI-safe. See `ABI Compatibility Considerations'
189*aca3beaaSApple OSS Distributions  *      below for more details on ABI-safety. In the user-space code,
190*aca3beaaSApple OSS Distributions  *      the macro is guarded by the `__CCT_ENABLE_USER_SPACE' compilation
191*aca3beaaSApple OSS Distributions  *      flag.
192*aca3beaaSApple OSS Distributions  *      When used in the kernel-space code, the macro will declare
193*aca3beaaSApple OSS Distributions  *      the common constrained types.
194*aca3beaaSApple OSS Distributions  *
195*aca3beaaSApple OSS Distributions  *      Examples:
196*aca3beaaSApple OSS Distributions  *
197*aca3beaaSApple OSS Distributions  *      (1) When used from the user space, and `__CCT_ENABLE_USER_SPACE'
198*aca3beaaSApple OSS Distributions  *          is defined, the expression
199*aca3beaaSApple OSS Distributions  *          `__CCT_DECLARE_CONSTRAINED_PTR_TYPES(struct socket, socket);'
200*aca3beaaSApple OSS Distributions  *           will declare types:
201*aca3beaaSApple OSS Distributions  *
202*aca3beaaSApple OSS Distributions  *          (a) `socket_ref_t': the `reference' to `struct socket'
203*aca3beaaSApple OSS Distributions  *          (b) `socket_ref_ref_t': the `reference to reference'
204*aca3beaaSApple OSS Distributions  *              to `struct socket'.
205*aca3beaaSApple OSS Distributions  *
206*aca3beaaSApple OSS Distributions  *      (2) When used from the kernel space,
207*aca3beaaSApple OSS Distributions  *          `__CCT_DECLARE_CONSTRAINED_PTR_TYPES(struct socket, socket);'
208*aca3beaaSApple OSS Distributions  *           will declare the above types, plus:
209*aca3beaaSApple OSS Distributions  *
210*aca3beaaSApple OSS Distributions  *          (c) `socket_ptr_t': `checked' pointer to `struct socket'.
211*aca3beaaSApple OSS Distributions  *          (d) `socket_bptr_t': `bidirectional' pointer to `struct socket'.
212*aca3beaaSApple OSS Distributions  *          (e) `socket_ref_ptr_t': `checked' pointer to a `reference'
213*aca3beaaSApple OSS Distributions  *              to `struct socket'.
214*aca3beaaSApple OSS Distributions  *          (f) `socket_ptr_ref_t': `reference' to a `checked' pointer
215*aca3beaaSApple OSS Distributions  *              to `struct socket'.
216*aca3beaaSApple OSS Distributions  *
217*aca3beaaSApple OSS Distributions  *      These additional types are not ABI-safe, and therefore are not exposed
218*aca3beaaSApple OSS Distributions  *      to the user space. See `ABI Compatibility Considerations' below.
219*aca3beaaSApple OSS Distributions  *
220*aca3beaaSApple OSS Distributions  *
221*aca3beaaSApple OSS Distributions  * 2.2. Declaring individual constrained types.
222*aca3beaaSApple OSS Distributions  *
223*aca3beaaSApple OSS Distributions  *      The above macro attempts to do many things at once, and under some
224*aca3beaaSApple OSS Distributions  *      circumstances can be not appropriate. For these circumstances, a
225*aca3beaaSApple OSS Distributions  *      finer-graned declarator can be used:
226*aca3beaaSApple OSS Distributions  *
227*aca3beaaSApple OSS Distributions  *      `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, ...)'
228*aca3beaaSApple OSS Distributions  *
229*aca3beaaSApple OSS Distributions  *      Parameters:
230*aca3beaaSApple OSS Distributions  *
231*aca3beaaSApple OSS Distributions  *      `basetype`: the pointee type.
232*aca3beaaSApple OSS Distributions  *      `basetag`:  the prefix of the constrained type.
233*aca3beaaSApple OSS Distributions  *      `...`:      list of constraints:
234*aca3beaaSApple OSS Distributions  *                  - `__CCT_REF' for the "reference" contract;
235*aca3beaaSApple OSS Distributions  *                  - `__CCT_CREF' for the "const reference" contract;
236*aca3beaaSApple OSS Distributions  *                  - `__CCT_PTR' for the "checked pointer" contract; or
237*aca3beaaSApple OSS Distributions  *                  - `__CCT_BPTR' for the "bidirectional pointer" contract.
238*aca3beaaSApple OSS Distributions  *
239*aca3beaaSApple OSS Distributions  *      Examples:
240*aca3beaaSApple OSS Distributions  *
241*aca3beaaSApple OSS Distributions  *      (1) `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct socket, socket, __CCT_REF)'
242*aca3beaaSApple OSS Distributions  *          will declare the type
243*aca3beaaSApple OSS Distributions  *              `reference' pointer to `struct socket'
244*aca3beaaSApple OSS Distributions  *          and call this type by `socket_ref_t'
245*aca3beaaSApple OSS Distributions  *
246*aca3beaaSApple OSS Distributions  *      (2) `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct socket, socket, __CCT_REF, __CCT_PTR)'
247*aca3beaaSApple OSS Distributions  *          will declare the type
248*aca3beaaSApple OSS Distributions  *              `checked' pointer to `socket_ref_t'
249*aca3beaaSApple OSS Distributions  *          which in turn is equivalent to the type
250*aca3beaaSApple OSS Distributions  *              `checked' pointer to `reference' pointer to `struct socket'
251*aca3beaaSApple OSS Distributions  *
252*aca3beaaSApple OSS Distributions  *      (3) `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct socket, socket, __CCT_REF, __CCT_PTR, __CCT_REF)'
253*aca3beaaSApple OSS Distributions  *          will declare the type
254*aca3beaaSApple OSS Distributions  *              `reference' pointer to `socket_ref_ptr_t'
255*aca3beaaSApple OSS Distributions  *          which is equivalent to the type
256*aca3beaaSApple OSS Distributions  *              `reference' pointer to `checked' pointer to `socket_ref_t'
257*aca3beaaSApple OSS Distributions  *          which in turn is equivalent to the type
258*aca3beaaSApple OSS Distributions  *              `reference' pointer to `checked' pointer to `reference' pointer to `struct socket'
259*aca3beaaSApple OSS Distributions  *
260*aca3beaaSApple OSS Distributions  *
261*aca3beaaSApple OSS Distributions  * 3. Using constrained pointer types.
262*aca3beaaSApple OSS Distributions  *
263*aca3beaaSApple OSS Distributions  * 3.1. Using constrained pointers for local variables.
264*aca3beaaSApple OSS Distributions  *
265*aca3beaaSApple OSS Distributions  *      Constraining the pointers on the stack reduces the risk of stack
266*aca3beaaSApple OSS Distributions  *      overflow. Therefore, it is highly suggested to use the constrained
267*aca3beaaSApple OSS Distributions  *      versions of the pointers for stack parameters. For local array
268*aca3beaaSApple OSS Distributions  *      variables, opt for the `bidirectional' pointers. If only a single value
269*aca3beaaSApple OSS Distributions  *      needs to be pointed, opt for the `reference' pointers.
270*aca3beaaSApple OSS Distributions  *
271*aca3beaaSApple OSS Distributions  *      There are two alternative approaches for using the `reference' pointers.
272*aca3beaaSApple OSS Distributions  *      One approach is to explicitly use `thing_ref_t ptr` instead of `thing *ptr`.
273*aca3beaaSApple OSS Distributions  *      The other approach is to surround the code with the directives
274*aca3beaaSApple OSS Distributions  *      `__ASSUME_PTR_ABI_SINGLE_BEGIN' and `__ASSUME_PTR_ABI_SINGLE_END', which
275*aca3beaaSApple OSS Distributions  *      will have the effect of turning every unconstrained pointer to its
276*aca3beaaSApple OSS Distributions  *      `reference' counterpart.
277*aca3beaaSApple OSS Distributions  *
278*aca3beaaSApple OSS Distributions  *
279*aca3beaaSApple OSS Distributions  * 3.2. Using constrained pointers for function parameters
280*aca3beaaSApple OSS Distributions  *
281*aca3beaaSApple OSS Distributions  * 3.2.1. Use `reference' pointers for scalar parameters.
282*aca3beaaSApple OSS Distributions  *
283*aca3beaaSApple OSS Distributions  *      Scalar parameters are safe to use across ABI boundaries.
284*aca3beaaSApple OSS Distributions  *
285*aca3beaaSApple OSS Distributions  *      Examples:
286*aca3beaaSApple OSS Distributions  *
287*aca3beaaSApple OSS Distributions  *      (1) Using `reference' pointers for scalar input:
288*aca3beaaSApple OSS Distributions  *
289*aca3beaaSApple OSS Distributions  *      errno_t thing_is_valid(const thing_ref_t t)
290*aca3beaaSApple OSS Distributions  *      {
291*aca3beaaSApple OSS Distributions  *              return t == NULL ? EINVAL : 0;
292*aca3beaaSApple OSS Distributions  *      }
293*aca3beaaSApple OSS Distributions  *
294*aca3beaaSApple OSS Distributions  *
295*aca3beaaSApple OSS Distributions  *      (2) Using `reference' pointers for scalar output, which is
296*aca3beaaSApple OSS Distributions  *          allocated by the caller:
297*aca3beaaSApple OSS Distributions  *
298*aca3beaaSApple OSS Distributions  *      errno_t thing_copy(const thing_ref_t src, thing_ref_t dst)
299*aca3beaaSApple OSS Distributions  *      {
300*aca3beaaSApple OSS Distributions  *              if (src == NULL || dst == NULL) {
301*aca3beaaSApple OSS Distributions  *                      return EINVAL;
302*aca3beaaSApple OSS Distributions  *              }
303*aca3beaaSApple OSS Distributions  *              bcopy(src, dst);
304*aca3beaaSApple OSS Distributions  *              return 0;
305*aca3beaaSApple OSS Distributions  *      }
306*aca3beaaSApple OSS Distributions  *
307*aca3beaaSApple OSS Distributions  *      (3) Using `reference to reference' for scalar output that is
308*aca3beaaSApple OSS Distributions  *          allocated by the callee:
309*aca3beaaSApple OSS Distributions  *
310*aca3beaaSApple OSS Distributions  *      errno_t thing_dup(const thing_ref_t src, thing_ref_ref_t dst)
311*aca3beaaSApple OSS Distributions  *      {
312*aca3beaaSApple OSS Distributions  *              *dst = malloc(sizeof(*dst));
313*aca3beaaSApple OSS Distributions  *              bcopy(src, *dst, sizeof(*src));
314*aca3beaaSApple OSS Distributions  *              return 0;
315*aca3beaaSApple OSS Distributions  *      }
316*aca3beaaSApple OSS Distributions  *
317*aca3beaaSApple OSS Distributions  *
318*aca3beaaSApple OSS Distributions  * 3.2.2. Use `checked' pointers for vector parameters.
319*aca3beaaSApple OSS Distributions  *
320*aca3beaaSApple OSS Distributions  *      When the ABI isn't a concern, use of `checked' pointers
321*aca3beaaSApple OSS Distributions  *      increases the code readability.
322*aca3beaaSApple OSS Distributions  *
323*aca3beaaSApple OSS Distributions  *      See `ABI Compatibility Considerations' below for vector parameters when
324*aca3beaaSApple OSS Distributions  *      ABI is a concern.
325*aca3beaaSApple OSS Distributions  *
326*aca3beaaSApple OSS Distributions  *      Examples:
327*aca3beaaSApple OSS Distributions  *
328*aca3beaaSApple OSS Distributions  *      (1) Using `checked' pointers for vector input:
329*aca3beaaSApple OSS Distributions  *
330*aca3beaaSApple OSS Distributions  *      errno_t thing_find_best(const thing_ref_ptr_t things,
331*aca3beaaSApple OSS Distributions  *                              thing_ref_ref_t best, size_t count)
332*aca3beaaSApple OSS Distributions  *      {
333*aca3beaaSApple OSS Distributions  *              for (int i = 0; i < count; i++) {
334*aca3beaaSApple OSS Distributions  *                      if (thing_is_the_best(things[i])) {
335*aca3beaaSApple OSS Distributions  *                              *best = things[i];
336*aca3beaaSApple OSS Distributions  *                              return 0;
337*aca3beaaSApple OSS Distributions  *                      }
338*aca3beaaSApple OSS Distributions  *              }
339*aca3beaaSApple OSS Distributions  *              return ENOENT; // no best thing
340*aca3beaaSApple OSS Distributions  *      }
341*aca3beaaSApple OSS Distributions  *
342*aca3beaaSApple OSS Distributions  *      (2) Using `checked' pointers for vector output parameters that
343*aca3beaaSApple OSS Distributions  *          are allocated by caller:
344*aca3beaaSApple OSS Distributions  *
345*aca3beaaSApple OSS Distributions  *      errno_t thing_copy_things(thing_ref_ptr_t src, thing_ref_ptr_t dst,
346*aca3beaaSApple OSS Distributions  *                                size_t count)
347*aca3beaaSApple OSS Distributions  *      {
348*aca3beaaSApple OSS Distributions  *              for (int i = 0; i < count; i++) {
349*aca3beaaSApple OSS Distributions  *                      dst[i] = malloc(sizeof(*dst[i]));
350*aca3beaaSApple OSS Distributions  *                      bcopy(src[i], dst[i], sizeof(*src[i]));
351*aca3beaaSApple OSS Distributions  *              }
352*aca3beaaSApple OSS Distributions  *              return 0;
353*aca3beaaSApple OSS Distributions  *      }
354*aca3beaaSApple OSS Distributions  *
355*aca3beaaSApple OSS Distributions  *      (3) Using `reference to checked' pointers for vector output
356*aca3beaaSApple OSS Distributions  *      parameters that are allocated by callee:
357*aca3beaaSApple OSS Distributions  *
358*aca3beaaSApple OSS Distributions  *      errno_t thing_dup_things(thing_ref_ptr_t src, thing_ref_ptr_ref_t dst,
359*aca3beaaSApple OSS Distributions  *                               size_t count)
360*aca3beaaSApple OSS Distributions  *      {
361*aca3beaaSApple OSS Distributions  *              *dst = malloc(sizeof(**src) * count);
362*aca3beaaSApple OSS Distributions  *              return thing_copy_things(src, *dst, count);
363*aca3beaaSApple OSS Distributions  *      }
364*aca3beaaSApple OSS Distributions  *
365*aca3beaaSApple OSS Distributions  *
366*aca3beaaSApple OSS Distributions  * 3.3. Using constrained pointers in struct definitions
367*aca3beaaSApple OSS Distributions  *
368*aca3beaaSApple OSS Distributions  *      Examples:
369*aca3beaaSApple OSS Distributions  *
370*aca3beaaSApple OSS Distributions  *      (1) Using a structure that points to array of things:
371*aca3beaaSApple OSS Distributions  *
372*aca3beaaSApple OSS Distributions  *      struct things_crate {
373*aca3beaaSApple OSS Distributions  *              size_t       tc_count;
374*aca3beaaSApple OSS Distributions  *              thing_bptr_t tc_things;
375*aca3beaaSApple OSS Distributions  *      };
376*aca3beaaSApple OSS Distributions  *
377*aca3beaaSApple OSS Distributions  *
378*aca3beaaSApple OSS Distributions  * 3.4. Variable-size structures
379*aca3beaaSApple OSS Distributions  *
380*aca3beaaSApple OSS Distributions  *      Constrained pointer instrumentation depends on knowing the size of the
381*aca3beaaSApple OSS Distributions  *      structures. If the structure contains a variable array, the array needs
382*aca3beaaSApple OSS Distributions  *      to be annotated by `__sized_by' or `__counted_by' attribute:
383*aca3beaaSApple OSS Distributions  *
384*aca3beaaSApple OSS Distributions  *      Example:
385*aca3beaaSApple OSS Distributions  *
386*aca3beaaSApple OSS Distributions  *      struct sockaddr {
387*aca3beaaSApple OSS Distributions  *              __uint8_t       sa_len;
388*aca3beaaSApple OSS Distributions  *              sa_family_t     sa_family;
389*aca3beaaSApple OSS Distributions  *              char            sa_data[__counted_by(sa_len - 2)];
390*aca3beaaSApple OSS Distributions  *      };
391*aca3beaaSApple OSS Distributions  *
392*aca3beaaSApple OSS Distributions  *
393*aca3beaaSApple OSS Distributions  * 4. ABI Compatibility Considerations
394*aca3beaaSApple OSS Distributions  *
395*aca3beaaSApple OSS Distributions  *      The pointer instrumentation process has ABI implications.
396*aca3beaaSApple OSS Distributions  *
397*aca3beaaSApple OSS Distributions  *      When the pointer insrumentation is enabled, the size of `bidirectional'
398*aca3beaaSApple OSS Distributions  *      and `checked' pointers exceeds the size of the machine word.
399*aca3beaaSApple OSS Distributions  *
400*aca3beaaSApple OSS Distributions  *      Thus, if there is a concern that the instrumentation is enabled only in
401*aca3beaaSApple OSS Distributions  *      some compilation units that use the function, these constrained
402*aca3beaaSApple OSS Distributions  *      pointers can not be used for function parameters.
403*aca3beaaSApple OSS Distributions  *
404*aca3beaaSApple OSS Distributions  *      Instead, one should rely on `__counted_by(count)' or `__sized_by(size)'
405*aca3beaaSApple OSS Distributions  *      attributes. These attributes accept as a parameter the name of a
406*aca3beaaSApple OSS Distributions  *      variable that contains the cont of items, or the byte size, of the
407*aca3beaaSApple OSS Distributions  *      pointed-to array. Use of these attributes does not change the size of
408*aca3beaaSApple OSS Distributions  *      the pointer.
409*aca3beaaSApple OSS Distributions  *
410*aca3beaaSApple OSS Distributions  *      The tradeoff is between maintaining code readabilty and ABI compatibility.
411*aca3beaaSApple OSS Distributions  *
412*aca3beaaSApple OSS Distributions  *      A common pattern is to split the function into the implementation,
413*aca3beaaSApple OSS Distributions  *      which is statically linked and therefore is ABI-safe, and the interface
414*aca3beaaSApple OSS Distributions  *      wrapper, which uses `__counted_by' or `__sized_by' to preserve ABI
415*aca3beaaSApple OSS Distributions  *      compatibility.
416*aca3beaaSApple OSS Distributions  *
417*aca3beaaSApple OSS Distributions  *
418*aca3beaaSApple OSS Distributions  * 4.1. When ABI is a concern, replace `bidirectional' and `checked'
419*aca3beaaSApple OSS Distributions  *        with  `__counted_by(count)` and `__sized_by(size)` for vector
420*aca3beaaSApple OSS Distributions  *        parameters.
421*aca3beaaSApple OSS Distributions  *
422*aca3beaaSApple OSS Distributions  *
423*aca3beaaSApple OSS Distributions  *      Examples:
424*aca3beaaSApple OSS Distributions  *
425*aca3beaaSApple OSS Distributions  *      (1) Using `const thing_ref_t __counted_by(count)' instead of `const
426*aca3beaaSApple OSS Distributions  *          thing_ref_ptr_t' for vector input in a wrapper:
427*aca3beaaSApple OSS Distributions  *
428*aca3beaaSApple OSS Distributions  *      errno_t thing_find_best_compat(const thing_ref_t __counted_by(count)things,
429*aca3beaaSApple OSS Distributions  *                                     thing_ref_ref_t best, size_t count)
430*aca3beaaSApple OSS Distributions  *      {
431*aca3beaaSApple OSS Distributions  *              // __counted_by implicitly upgraded to `checked'
432*aca3beaaSApple OSS Distributions  *              return thing_find_best(things, best, count);
433*aca3beaaSApple OSS Distributions  *      }
434*aca3beaaSApple OSS Distributions  *
435*aca3beaaSApple OSS Distributions  *      (2) Using `thing_ref_t __counted_by(count)' instead of `thing_ref_ptr_t'
436*aca3beaaSApple OSS Distributions  *          for vector output in a wrapper.
437*aca3beaaSApple OSS Distributions  *
438*aca3beaaSApple OSS Distributions  *      errno_t thing_copy_things_compat(thing_ref_t __counted_by(count)src,
439*aca3beaaSApple OSS Distributions  *                                       things_ref_t __counted_by(count)dst,
440*aca3beaaSApple OSS Distributions  *                                       size_t count)
441*aca3beaaSApple OSS Distributions  *      {
442*aca3beaaSApple OSS Distributions  *              // __counted_by implicitly upgraded to `checked'
443*aca3beaaSApple OSS Distributions  *              return thing_copy_things(src, dst, count);
444*aca3beaaSApple OSS Distributions  *      }
445*aca3beaaSApple OSS Distributions  *
446*aca3beaaSApple OSS Distributions  *
447*aca3beaaSApple OSS Distributions  * 4.2. When ABI is a concern, use `__counted_by(count)' and
448*aca3beaaSApple OSS Distributions  *        `__sized_by(size)' for struct members that point to arrays.
449*aca3beaaSApple OSS Distributions  *
450*aca3beaaSApple OSS Distributions  *      Examples:
451*aca3beaaSApple OSS Distributions  *
452*aca3beaaSApple OSS Distributions  *      (1) Using a structure that points to array of things:
453*aca3beaaSApple OSS Distributions  *
454*aca3beaaSApple OSS Distributions  *      struct things_crate {
455*aca3beaaSApple OSS Distributions  *              size_t                               tc_count;
456*aca3beaaSApple OSS Distributions  *              struct thing * __counted_by(tc_count)tc_things;
457*aca3beaaSApple OSS Distributions  *      };
458*aca3beaaSApple OSS Distributions  *
459*aca3beaaSApple OSS Distributions  * 5. Naming conventions
460*aca3beaaSApple OSS Distributions  *
461*aca3beaaSApple OSS Distributions  *      If `typename' is the name of a C type, and `tag' is a constraint tag
462*aca3beaaSApple OSS Distributions  *      (one of `ref', `ptr', or `bptr'), then the name of a pointer to
463*aca3beaaSApple OSS Distributions  *      `typename' constrained by `tag' is `basetag_tag_t', where `basename'
464*aca3beaaSApple OSS Distributions  *      is defined by:
465*aca3beaaSApple OSS Distributions  *
466*aca3beaaSApple OSS Distributions  *      (a) If `typename' is a name of an integral type, then `basetag' is same
467*aca3beaaSApple OSS Distributions  *          as `typename'.
468*aca3beaaSApple OSS Distributions  *      (b) If `typename' is a name of a function type, then `basetag' is same
469*aca3beaaSApple OSS Distributions  *          as `typename'.
470*aca3beaaSApple OSS Distributions  *      (c) If `typename' is a name of a structure, then `basetag' is formed by
471*aca3beaaSApple OSS Distributions  *          stripping the `struct' keyword from `typename'.
472*aca3beaaSApple OSS Distributions  *      (d) If `typename' is a name of an enumeration, then `basetag' is formed
473*aca3beaaSApple OSS Distributions  *          by stripping the `enum' keyword from `typename'.
474*aca3beaaSApple OSS Distributions  *      (e) If `typename' is a name of a typedef to a struct or an enum that ends
475*aca3beaaSApple OSS Distributions  *          with `_t', then `basetag' is formed by stripping the `_t' suffix
476*aca3beaaSApple OSS Distributions  *          from `typename'. See (h) below for when `typename' is a pointer typedef.
477*aca3beaaSApple OSS Distributions  *      (f) If `typename' is a name of constrained pointer type ending with `_t',
478*aca3beaaSApple OSS Distributions  *          then `basetag' is formed by stripping the `_t' suffix from `typename'.
479*aca3beaaSApple OSS Distributions  *
480*aca3beaaSApple OSS Distributions  *      Additionally, constrained pointers to constrained const pointers are a
481*aca3beaaSApple OSS Distributions  *      special case:
482*aca3beaaSApple OSS Distributions  *
483*aca3beaaSApple OSS Distributions  *      (g) If `typename' is a name of a constrained pointer type, ending with
484*aca3beaaSApple OSS Distributions  *          `_{innertag}_t', and `typename' has `const' qualifier, then `basetag'
485*aca3beaaSApple OSS Distributions  *          is formed by replacing `_{innertag}_t' with `_c{innertag}'
486*aca3beaaSApple OSS Distributions  *
487*aca3beaaSApple OSS Distributions  *      Finally, sometimes `name_t' represents not `struct name' but `struct name *'.
488*aca3beaaSApple OSS Distributions  *      This creates additional special case:
489*aca3beaaSApple OSS Distributions  *
490*aca3beaaSApple OSS Distributions  *      (h) If `typename' is a pointer typedef named `{struct}_t`, such as
491*aca3beaaSApple OSS Distributions  *          `mbuf_t',  then creating a constrained pointer to a `typename' would
492*aca3beaaSApple OSS Distributions  *           require creating a  constrained pointer to an unconstrained pointer,
493*aca3beaaSApple OSS Distributions  *           which is not supported at the moment. Instead, a constrained pointer to
494*aca3beaaSApple OSS Distributions  *           `typeof(*typename)` must be created first, and constrained again. Using
495*aca3beaaSApple OSS Distributions  *           the `mbuf_t` example, first one should create a constrained pointer to
496*aca3beaaSApple OSS Distributions  *           `struct mbuf`, e.g, `mbuf_bptr_t`, and then constrain it again with
497*aca3beaaSApple OSS Distributions  *           `tag`, leading to `mbuf_bptr_ref_t'.
498*aca3beaaSApple OSS Distributions  *
499*aca3beaaSApple OSS Distributions  *      Examples:
500*aca3beaaSApple OSS Distributions  *
501*aca3beaaSApple OSS Distributions  *      (1) `int_ref_t' is a `reference pointer' to `int', following the rule (a) above.
502*aca3beaaSApple OSS Distributions  *      (2) `so_pru_ref_t' is a `reference pointer' to function `so_pru',
503*aca3beaaSApple OSS Distributions  *          following the rule (b) above.
504*aca3beaaSApple OSS Distributions  *      (3) `socket_ref_t' is a `reference pointer' to `struct socket',
505*aca3beaaSApple OSS Distributions  *          following the rule (c) above.
506*aca3beaaSApple OSS Distributions  *      (4) `classq_pkt_type_ref_t' is a `reference pointer' to `enum classq_pkt_type'
507*aca3beaaSApple OSS Distributions  *          following the rule (d) above.
508*aca3beaaSApple OSS Distributions  *      (5) `classq_pkt_type_ref_t' is a also `reference pointer' to `classq_pkt_type_t'
509*aca3beaaSApple OSS Distributions  *          following the rule (e) above.
510*aca3beaaSApple OSS Distributions  *      (6) `socket_ref_ref_t' is a `reference pointer' to `socket_ref_t`,
511*aca3beaaSApple OSS Distributions  *          following the rule (f) above.
512*aca3beaaSApple OSS Distributions  *      (7) `socket_cref_ref_t' is a `reference pointer' to `socket_ref_t const`,
513*aca3beaaSApple OSS Distributions  *          following the rule (g) above.
514*aca3beaaSApple OSS Distributions  *      (8) `mbuf_ref_ref_t', is a `reference pointer' to `mbuf_ref_t`, and is one
515*aca3beaaSApple OSS Distributions  *          possible result of creating a `reference pointer' to `mbuf_t',
516*aca3beaaSApple OSS Distributions  *          following the rule (h) above.
517*aca3beaaSApple OSS Distributions  *      (9) `mbuf_bptr_ref_t', is a `reference pointer' to `mbuf_bptr_t`, and
518*aca3beaaSApple OSS Distributions  *          is another possible result of creating a `reference pointer' to
519*aca3beaaSApple OSS Distributions  *          `mbuf_t', following the rule (h) above.
520*aca3beaaSApple OSS Distributions  *
521*aca3beaaSApple OSS Distributions  */
522*aca3beaaSApple OSS Distributions 
523*aca3beaaSApple OSS Distributions /*
524*aca3beaaSApple OSS Distributions  * Constraint contract constants.
525*aca3beaaSApple OSS Distributions  *
526*aca3beaaSApple OSS Distributions  * At the moment only clang (when compiled with `ptrcheck' feature) supports
527*aca3beaaSApple OSS Distributions  * pointer tagging via `__single', `__indexable' and `__bidi_indexable' attributes.
528*aca3beaaSApple OSS Distributions  *
529*aca3beaaSApple OSS Distributions  * During the transitional period, the `__indexable__' and `__bidi_indexable'
530*aca3beaaSApple OSS Distributions  * constraints will decay to raw pointers if the `ptrcheck' feature is not enabled.
531*aca3beaaSApple OSS Distributions  * Once the transitional period is over, the `__CCT_CONTRACT_ATTR_{B}PTR' constraints
532*aca3beaaSApple OSS Distributions  * will stop decaying to raw pointers when built by sufficiently recent version
533*aca3beaaSApple OSS Distributions  * of clang.
534*aca3beaaSApple OSS Distributions  *
535*aca3beaaSApple OSS Distributions  * Support for other compilers will be added after the introduction of support
536*aca3beaaSApple OSS Distributions  * for pointer tagging on those compilers.
537*aca3beaaSApple OSS Distributions  */
538*aca3beaaSApple OSS Distributions #if defined(KERNEL) || defined(__CCT_ENABLE_USER_SPACE)
539*aca3beaaSApple OSS Distributions #if defined(__clang__)
540*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_REF         __single
541*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_CREF        const __single
542*aca3beaaSApple OSS Distributions #if  __has_ptrcheck
543*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_BPTR        __bidi_indexable
544*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_PTR         __indexable
545*aca3beaaSApple OSS Distributions #else /* __clang__ + __has_ptrcheck */
546*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_BPTR
547*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_PTR
548*aca3beaaSApple OSS Distributions #endif /* __clang__ + !__has_ptrcheck */
549*aca3beaaSApple OSS Distributions #else /* !__clang__ */
550*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_REF
551*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_CREF        const
552*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_BPTR
553*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_ATTR___CCT_PTR
554*aca3beaaSApple OSS Distributions #endif /* __clang__ */
555*aca3beaaSApple OSS Distributions 
556*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_TAG___CCT_REF          _ref
557*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_TAG___CCT_CREF         _cref
558*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_TAG___CCT_BPTR         _bptr
559*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_TAG___CCT_PTR          _ptr
560*aca3beaaSApple OSS Distributions 
561*aca3beaaSApple OSS Distributions /* Helper macros */
562*aca3beaaSApple OSS Distributions #define __CCT_DEFER(F, ...) F(__VA_ARGS__)
563*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_TO_ATTR(kind) __CONCAT(__CCT_CONTRACT_ATTR_, kind)
564*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_TO_TAG(kind)  __CCT_DEFER(__CONCAT, __CCT_CONTRACT_TAG_, kind)
565*aca3beaaSApple OSS Distributions 
566*aca3beaaSApple OSS Distributions #define __CCT_COUNT_ARGS1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N
567*aca3beaaSApple OSS Distributions #define __CCT_COUNT_ARGS(...) \
568*aca3beaaSApple OSS Distributions 	__CCT_COUNT_ARGS1(, __VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
569*aca3beaaSApple OSS Distributions #define __CCT_DISPATCH1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
570*aca3beaaSApple OSS Distributions #define __CCT_DISPATCH(base, ...) \
571*aca3beaaSApple OSS Distributions 	__CCT_DISPATCH1(base, __CCT_COUNT_ARGS(__VA_ARGS__), __VA_ARGS__)
572*aca3beaaSApple OSS Distributions 
573*aca3beaaSApple OSS Distributions /* Covert a contract list to a type suffix */
574*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_1(kind)                                                \
575*aca3beaaSApple OSS Distributions 	__CCT_DEFER(__CONCAT, __CCT_CONTRACT_TO_TAG(kind), _t)
576*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_2(kind1, kind2)                                        \
577*aca3beaaSApple OSS Distributions 	__CCT_DEFER(__CONCAT, __CCT_CONTRACT_TO_TAG(kind1),                                             \
578*aca3beaaSApple OSS Distributions 	         __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_1(kind2))
579*aca3beaaSApple OSS Distributions #define __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_3(kind1, kind2, kind3)                                 \
580*aca3beaaSApple OSS Distributions 	__CCT_DEFER(__CONCAT, __CCT_CONTRACT_TO_TAG(kind1),                                             \
581*aca3beaaSApple OSS Distributions 	         __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_2(kind2, kind3))
582*aca3beaaSApple OSS Distributions 
583*aca3beaaSApple OSS Distributions /* Create typedefs for the constrained pointer type */
584*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPE_3(basetype, basetag, kind)                               \
585*aca3beaaSApple OSS Distributions typedef basetype * __CCT_CONTRACT_TO_ATTR(kind)                                                     \
586*aca3beaaSApple OSS Distributions 	__CCT_DEFER(__CONCAT, basetag,  __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_1(kind))
587*aca3beaaSApple OSS Distributions 
588*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPE_4(basetype, basetag, kind1, kind2)                       \
589*aca3beaaSApple OSS Distributions typedef basetype * __CCT_CONTRACT_TO_ATTR(kind1)                                                    \
590*aca3beaaSApple OSS Distributions 	         * __CCT_CONTRACT_TO_ATTR(kind2)                                                        \
591*aca3beaaSApple OSS Distributions 	__CCT_DEFER(__CONCAT, basetag,  __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_2(kind1, kind2))
592*aca3beaaSApple OSS Distributions 
593*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPE_5(basetype, basetag, kind1, kind2, kind3)                \
594*aca3beaaSApple OSS Distributions typedef basetype * __CCT_CONTRACT_TO_ATTR(kind1)                                                    \
595*aca3beaaSApple OSS Distributions 	         * __CCT_CONTRACT_TO_ATTR(kind2)                                                        \
596*aca3beaaSApple OSS Distributions 	         * __CCT_CONTRACT_TO_ATTR(kind3)                                                        \
597*aca3beaaSApple OSS Distributions 	__CCT_DEFER(__CONCAT, basetag,  __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_3(kind1, kind2, kind3))
598*aca3beaaSApple OSS Distributions #endif /* defined(KERNEL) || defined(__CCT_ENABLE_USER_SPACE) */
599*aca3beaaSApple OSS Distributions 
600*aca3beaaSApple OSS Distributions /*
601*aca3beaaSApple OSS Distributions  * Lower level type constructor.
602*aca3beaaSApple OSS Distributions  */
603*aca3beaaSApple OSS Distributions #if defined(KERNEL) || defined(__CCT_ENABLE_USER_SPACE)
604*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, ...)                                  \
605*aca3beaaSApple OSS Distributions 	__CCT_DISPATCH(__CCT_DECLARE_CONSTRAINED_PTR_TYPE, basetype, basetag, __VA_ARGS__)
606*aca3beaaSApple OSS Distributions #else /* !defined(KERNEL) && !defined(__CCT_ENABLE_USER_SPACE) */
607*aca3beaaSApple OSS Distributions #if defined(__clang__)
608*aca3beaaSApple OSS Distributions #pragma clang diagnostic push
609*aca3beaaSApple OSS Distributions #pragma clang diagnostic ignored "-Wextra-semi"
610*aca3beaaSApple OSS Distributions #endif /* defined(__clang__) */
611*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, ...)
612*aca3beaaSApple OSS Distributions #if defined(__clang__)
613*aca3beaaSApple OSS Distributions #pragma clang diagnostic pop
614*aca3beaaSApple OSS Distributions #endif /* defined(__clang__) */
615*aca3beaaSApple OSS Distributions #endif /* !defined(KERNEL) && !defined(__CCT_ENABLE_USER_SPACE) */
616*aca3beaaSApple OSS Distributions 
617*aca3beaaSApple OSS Distributions /*
618*aca3beaaSApple OSS Distributions  * Higher level type constructors.
619*aca3beaaSApple OSS Distributions  */
620*aca3beaaSApple OSS Distributions #if defined(KERNEL)
621*aca3beaaSApple OSS Distributions /*
622*aca3beaaSApple OSS Distributions  * The constrained types that can potentially break the ABI are not exposed
623*aca3beaaSApple OSS Distributions  * into the user-space.
624*aca3beaaSApple OSS Distributions  */
625*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)                                      \
626*aca3beaaSApple OSS Distributions __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_REF);                                   \
627*aca3beaaSApple OSS Distributions __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_BPTR);                                  \
628*aca3beaaSApple OSS Distributions __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_PTR);                                   \
629*aca3beaaSApple OSS Distributions __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_REF, __CCT_REF);                        \
630*aca3beaaSApple OSS Distributions __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_REF, __CCT_PTR);                        \
631*aca3beaaSApple OSS Distributions __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_PTR, __CCT_REF)
632*aca3beaaSApple OSS Distributions #else /* !defined(KERNEL) */
633*aca3beaaSApple OSS Distributions #if defined(__CCT_ENABLE_USER_SPACE)
634*aca3beaaSApple OSS Distributions /* Limiting the higher-level constructor to the ABI-preserving constructs. */
635*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)                                      \
636*aca3beaaSApple OSS Distributions 	__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_REF);                               \
637*aca3beaaSApple OSS Distributions 	__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, __CCT_REF, __CCT_REF)
638*aca3beaaSApple OSS Distributions #else /* !defined(__CCT_ENABLE_USER_SPACE) */
639*aca3beaaSApple OSS Distributions /* Disabling the higher-level constructor */
640*aca3beaaSApple OSS Distributions #if defined(__clang__)
641*aca3beaaSApple OSS Distributions #pragma clang diagnostic push
642*aca3beaaSApple OSS Distributions #pragma clang diagnostic ignored "-Wextra-semi"
643*aca3beaaSApple OSS Distributions #endif /* defined(__clang__) */
644*aca3beaaSApple OSS Distributions #define __CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)
645*aca3beaaSApple OSS Distributions #if defined(__clang__)
646*aca3beaaSApple OSS Distributions #pragma clang diagnostic pop
647*aca3beaaSApple OSS Distributions #endif /* defined(__clang__) */
648*aca3beaaSApple OSS Distributions #endif /* !defined(__CCT_ENABLE_USER_SPACE) */
649*aca3beaaSApple OSS Distributions #endif /* !defined(KERNEL) */
650*aca3beaaSApple OSS Distributions 
651*aca3beaaSApple OSS Distributions #endif /* __CONSTRAINED_CTYPES__ */
652