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