Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
/*
 * Copyright (c) 2000-2022 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */

#ifndef __CONSTRAINED_CTYPES__
#define __CONSTRAINED_CTYPES__

#include <sys/cdefs.h>

/* This file introduces macros for constraining pointer
 * types to specific contracts:
 *
 *
 * 1. List of supported constrained pointers.
 *
 * 1.1. `Reference' pointers.
 *
 *      The `reference' pointers point to a single entity. The pointer
 *      arithmetics are not supported for the `reference' pointers.
 *
 *      The `reference' pointers are fully ABI compatible with
 *      the unconstrained C pointers.
 *
 *      The naming convention for the `reference' pointers uses
 *      the `ref' constraint tag. See `Naming conventions' below for furhter
 *      discussion.
 *
 *      Examples:
 *
 *      (1) `socket_ref_t' is `reference' pointer to `struct socket'.
 *      (2) `uint32_ref_t' is `reference' pointer to `uint32_t'.
 *
 *
 * 1.2. `Checked' pointers.
 *
 *      The `checked' pointers represent contigous data arrays, which
 *      can be traversed only in the direction of increasing memory addresses.
 *      The pointer arithmetics are partially supported: decrements (p--, --p)
 *      are disallowed.
 *
 *      The `checked' pointers are not ABI-compatible with plain C pointers,
 *      due to the boundary checks instrumentation. See `ABI
 *      Compatibility Considerations' below for further discussion.
 *
 *      The naming convention for the `checked' pointers uses the `ptr'
 *      constraint tag. See `Naming conventions' below for furhter discussion.
 *
 *      Examples:
 *
 *      (1) `socket_ptr_t' is `checked' pointer to `struct socket'.
 *      (2) `uint32_ptr_t' is `checked' pointer to `uint32_t'.
 *
 *
 * 1.3. `Bidirectional' pointers.
 *
 *      The `bidirectional' pointers represent contigous data arrays,
 *      which can be traversed in both directions. The pointer arithmetics are
 *      fully supported for the `array' pointers.
 *
 *      The `bidirectional' pointers are not ABI-compatible with plain C
 *      pointers, due to the boundary checks instrumentation. Additionally,
 *      passing `bidirectional' pointers to functions require the use of stack.
 *      See `ABI Compatibility Considerations' below for further discussion.
 *
 *      The naming convention for the `bidirectional' pointers uses
 *      the `bptr' constraint tag. See `Naming conventions' below for furhter
 *      discussion.
 *
 *      Examples:
 *
 *      (1) `socket_bptr_t' is `bidirectional' pointer to `struct socket'.
 *      (2) `uint32_bptr_t' is `bidirectional' pointer to `uint32_t'.
 *
 *
 * 1.4. Multidimensional constrained pointers.
 *
 *      Constraining multidimensional pointers is achieved by iteratively
 *      applying the constraints from the innermost type to the outermost type.
 *
 *      Pointer arithmetics are supported for the dimensions that
 *      are not constrained to a `reference' or `const reference'.
 *
 *      If any of the dimension constraints isn't ABI-compatible with its
 *      unconstrained counterpart, then the entire constrained multidimensional
 *      pointer is not ABI-compatible with the corresponding unconstrained
 *      multidimensional pointer. Otherwise, the two are ABI-compatible. See
 *      `ABI compatibility' below for further discussion.
 *
 *      The naming convention for the multidimensional constrained pointers
 *      combines the naming tags that correspond to the individual constraints.
 *      See `Naming conventions' below for furhter discussion.
 *
 *      Examples:
 *
 *      (1) `socket_ref_bptr_t' is a `bidirectional' pointer to a `reference'
 *          pointer to `struct socket'.
 *      (2) `socket_ptr_ref_t' is a `reference' pointer to a `checked'
 *          pointer to `struct socket'.
 *
 *
 * 1.5. Using `const', `volatile', and `restrict' type qualifiers with
 *      constrained types.
 *
 *      The use of the `const', `volatile', and `restrict' type qualifiers
 *      (a.k.a. "CRV qualifiers") follows the syntax of the C language.
 *
 *      As a special case, if a `const' qualifier is applied to inner
 *      dimensions of a multidimensional constrained pointer type, the
 *      constraint tag is prepended with letter `c'; thus `cref' can be used
 *      for const-qualified `reference' pointer. This abbreviation is only
 *      supported for the `const' qualifier, as use of `volatile' or `restrict'
 *      for inner constrained types is quite uncommon. See `Multidimensional
 *      constrained pointers' above and `Naming conventions' below for further
 *      discussion.
 *
 *      Examples:
 *
 *      (1) `socket_ref_t const' is the const-qualified `reference' pointer
 *          to `struct socket'.
 *      (2) `socket_ptr_t volatile' is the volatile-qualified `checked' pointer
 *          to `struct socket'.
 *      (3) `socket_ptr_ref_t const' is a const-qualified `reference' pointer
 *          to a `checked' pointer to `struct socket'.
 *      (4) `socket_cref_ptr_t const' is a `checked' pointer to a
 *          const-qualified `reference' pointer to `struct socket'.
 *
 *
 * 1.6. Combining constrained pointers and unconstrained pointers.
 *
 *      Unconstrained pointers to constrained pointers follow
 *      the standard C syntax. Defining constrained pointers to
 *      unconstrained pointers is possible via defining a constrained pointer
 *      to a typedef.
 *
 *      Examples:
 *
 *      (1) `socket_ref_t *' is an unconstrained pointer to `socket_ref_t', i.e.
 *          unconstrained pointer to a `reference' pointer to `struct socket'.
 *      (2) `socket_ref_t const *' is an unconstrained pointer to `socket_ref_t const',
 *          i.e. an unconstrained pointer to a const-qualified `reference'
 *          pointer to `struct socket'.
 *      (3) `socket_ref_t * const' is a const-qualified unconstrained pointer to
 *          `socket_ref_t', i.e. a const-qualified unconstrained pointer to a
 *          `reference' pointer to `struct socket'.
 *      (4) `intptr_ref_t' is a `reference' pointer to `intptr_t', i.e.
 *          a `reference' pointer to an unconstrained pointer to `int'. Note
 *          the use of `intptr_t' typedef, which is necessary at the moment.
 *
 *
 * 2. Defining constrained pointer types.
 *
 * 2.1. Declaring multiple constrained types simultaneously.
 *
 *      `__CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)`
 *      is the suggested way to declare constrained pointer types.
 *
 *      Parameters:
 *
 *      `basetype`: the pointee type, including `struct' or `enum' keywords.
 *      `basetag`:  the prefix of the constrained type.
 *
 *      This macro acts differently in the user-space and the kernel-space
 *      code. When used in the former, it will only declare types which are
 *      ABI-safe. See `ABI Compatibility Considerations' below for more details.
 *
 *      Examples:
 *
 *      (1) When used from the user space,
 *          `__CCT_DECLARE_CONSTRAINED_PTR_TYPES(struct socket, socket);'
 *           will declare types:
 *
 *          (a) `socket_ref_t': the `reference' to `struct socket'
 *          (b) `socket_ref_ref_t': the `reference to reference'
 *              to `struct socket'.
 *
 *      (2) When used from the kernel space,
 *          `__CCT_DECLARE_CONSTRAINED_PTR_TYPES(struct socket, socket);'
 *           will declare the above types, plus:
 *
 *          (c) `socket_ptr_t': `checked' pointer to `struct socket'.
 *          (d) `socket_bptr_t': `bidirectional' pointer to `struct socket'.
 *          (e) `socket_ref_ptr_t': `checked' pointer to a `reference'
 *              to `struct socket'.
 *          (f) `socket_ptr_ref_t': `reference' to a `checked' pointer
 *              to `struct socket'.
 *
 *      These additional types are not ABI-safe, and therefore are not exposed
 *      to the user space. See `ABI Compatibility Considerations' below.
 *
 *
 * 2.2. Declaring individual constrained types.
 *
 *      The above macro attempts to do many things at once, and under some
 *      circumstances can be not appropriate. For these circumstances, a
 *      finer-graned declarator can be used:
 *
 *      `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, ...)'
 *
 *      Parameters:
 *
 *      `basetype`: the pointee type.
 *      `basetag`:  the prefix of the constrained type.
 *      `...`:      list of `REF', `CREF', `BPTR' or `PTR', which represent
 *                  the desired constraints.
 *
 *      Examples:
 *
 *      (1) `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct socket, socket, REF)'
 *          will declare the type `socket_ref_t`:
 *
 *      (2) `__CCT_DECLARE_CONSTRAINED_PTR_TYPE(struct socket, socket, REF, PTR, REF)'
 *           will declare the type `socket_ref_ptr_ref_t`:
 *
 *
 * 3. Using constrained pointer types.
 *
 * 3.1. Using constrained pointers for local variables.
 *
 *      Constraining the pointers on the stack reduces the risk of stack
 *      overflow. Therefore, it is highly suggested to use the constrained
 *      versions of the pointers for stack parameters. For local array
 *      variables, opt for the `bidirectional' pointers. If only a single value
 *      needs to be pointed, opt for the `reference' pointers.
 *
 *      There are two alternative approaches for using the `reference' pointers.
 *      One approach is to explicitly use `thing_ref_t ptr` instead of `thing *ptr`.
 *      The other approach is to surround the code with the directives
 *      `__ASSUME_PTR_ABI_SINGLE_BEGIN' and `__ASSUME_PTR_ABI_SINGLE_END', which
 *      will have the effect of turning every unconstrained pointer to its
 *      `reference' counterpart.
 *
 *
 * 3.2. Using constrained pointers for function parameters
 *
 * 3.2.1. Use `reference' pointers for scalar parameters.
 *
 *      Scalar parameters are safe to use across ABI boundaries.
 *
 *      Examples:
 *
 *      (1) Using `reference' pointers for scalar input:
 *
 *      errno_t thing_is_valid(const thing_ref_t t)
 *      {
 *              return t == NULL ? EINVAL : 0;
 *      }
 *
 *
 *      (2) Using `reference' pointers for scalar output, which is
 *          allocated by the caller:
 *
 *      errno_t thing_copy(const thing_ref_t src, thing_ref_t dst)
 *      {
 *              if (src == NULL || dst == NULL) {
 *                      return EINVAL;
 *              }
 *              bcopy(src, dst);
 *              return 0;
 *      }
 *
 *      (3) Using `reference to reference' for scalar output that is
 *          allocated by the callee:
 *
 *      errno_t thing_dup(const thing_ref_t src, thing_ref_ref_t dst)
 *      {
 *              *dst = malloc(sizeof(*dst));
 *              bcopy(src, *dst, sizeof(*src));
 *              return 0;
 *      }
 *
 *
 * 3.2.2. Use `checked' pointers for vector parameters.
 *
 *      When the ABI isn't a concern, use of `checked' pointers
 *      increases the code readability.
 *
 *      See `ABI Compatibility Considerations' below for vector parameters when
 *      ABI is a concern.
 *
 *      Examples:
 *
 *      (1) Using `checked' pointers for vector input:
 *
 *      errno_t thing_find_best(const thing_ref_ptr_t things,
 *                              thing_ref_ref_t best, size_t count)
 *      {
 *              for (int i = 0; i < count; i++) {
 *                      if (thing_is_the_best(things[i])) {
 *                              *best = things[i];
 *                              return 0;
 *                      }
 *              }
 *              return ENOENT; // no best thing
 *      }
 *
 *      (2) Using `checked' pointers for vector output parameters that
 *          are allocated by caller:
 *
 *      errno_t thing_copy_things(thing_ref_ptr_t src, thing_ref_ptr_t dst,
 *                                size_t count)
 *      {
 *              for (int i = 0; i < count; i++) {
 *                      dst[i] = malloc(sizeof(*dst[i]));
 *                      bcopy(src[i], dst[i], sizeof(*src[i]));
 *              }
 *              return 0;
 *      }
 *
 *      (3) Using `reference to checked' pointers for vector output
 *      parameters that are allocated by callee:
 *
 *      errno_t thing_dup_things(thing_ref_ptr_t src, thing_ref_ptr_ref_t dst,
 *                               size_t count)
 *      {
 *              *dst = malloc(sizeof(**src) * count);
 *              return thing_copy_things(src, *dst, count);
 *      }
 *
 *
 * 3.3. Using constrained pointers in struct definitions
 *
 *      Examples:
 *
 *      (1) Using a structure that points to array of things:
 *
 *      struct things_crate {
 *              size_t       tc_count;
 *              thing_bptr_t tc_things;
 *      };
 *
 *
 * 3.4. Variable-size structures
 *
 *      Constrained pointer instrumentation depends on knowing the size of the
 *      structures. If the structure contains a variable array, the array needs
 *      to be annotated by `__sized_by' or `__counted_by' attribute:
 *
 *      Example:
 *
 *      struct sockaddr {
 *              __uint8_t       sa_len;
 *              sa_family_t     sa_family;
 *              char            sa_data[__counted_by(sa_len - 2)];
 *      };
 *
 *
 * 4. ABI Compatibility Considerations
 *
 *      The pointer instrumentation process has ABI implications.
 *
 *      When the pointer insrumentation is enabled, the size of `bidirectional'
 *      and `checked' pointers exceeds the size of the machine word.
 *
 *      Thus, if there is a concern that the instrumentation is enabled only in
 *      some compilation units that use the function, these constrained
 *      pointers can not be used for function parameters.
 *
 *      Instead, one should rely on `__counted_by(count)' or `__sized_by(size)'
 *      attributes. These attributes accept as a parameter the name of a
 *      variable that contains the cont of items, or the byte size, of the
 *      pointed-to array. Use of these attributes does not change the size of
 *      the pointer.
 *
 *      The tradeoff is between maintaining code readabilty and ABI compatibility.
 *
 *      A common pattern is to split the function into the implementation,
 *      which is statically linked and therefore is ABI-safe, and the interface
 *      wrapper, which uses `__counted_by' or `__sized_by' to preserve ABI
 *      compatibility.
 *
 *
 * 4.1. When ABI is a concern, replace `bidirectional' and `checked'
 *        with  `__counted_by(count)` and `__sized_by(size)` for vector
 *        parameters.
 *
 *
 *      Examples:
 *
 *      (1) Using `const thing_ref_t __counted_by(count)' instead of `const
 *          thing_ref_ptr_t' for vector input in a wrapper:
 *
 *      errno_t thing_find_best_compat(const thing_ref_t __counted_by(count)things,
 *                                     thing_ref_ref_t best, size_t count)
 *      {
 *              // __counted_by implicitly upgraded to `checked'
 *              return thing_find_best(things, best, count);
 *      }
 *
 *      (2) Using `thing_ref_t __counted_by(count)' instead of `thing_ref_ptr_t'
 *          for vector output in a wrapper.
 *
 *      errno_t thing_copy_things_compat(thing_ref_t __counted_by(count)src,
 *                                       things_ref_t __counted_by(count)dst,
 *                                       size_t count)
 *      {
 *              // __counted_by implicitly upgraded to `checked'
 *              return thing_copy_things(src, dst, count);
 *      }
 *
 *
 * 4.2. When ABI is a concern, use `__counted_by(count)' and
 *        `__sized_by(size)' for struct members that point to arrays.
 *
 *      Examples:
 *
 *      (1) Using a structure that points to array of things:
 *
 *      struct things_crate {
 *              size_t                               tc_count;
 *              struct thing * __counted_by(tc_count)tc_things;
 *      };
 *
 * 5. Naming conventions
 *
 *      If `typename' is the name of a C type, and `tag' is a constraint tag
 *      (one of `ref', `ptr', or `bptr'), then the name of a pointer to
 *      `typename' constrained by `tag' is `basetag_tag_t', where `basename'
 *      is defined by:
 *
 *      (a) If `typename' is a name of an integral type, then `basetag' is same
 *          as `typename'.
 *      (b) If `typename' is a name of a function type, then `basetag' is same
 *          as `typename'.
 *      (c) If `typename' is a name of a structure, then `basetag' is formed by
 *          stripping the `struct' keyword from `typename'.
 *      (d) If `typename' is a name of an enumeration, then `basetag' is formed
 *          by stripping the `enum' keyword from `typename'.
 *      (e) If `typename' is a name of a typedef to a struct or an enum that ends
 *          with `_t', then `basetag' is formed by stripping the `_t' suffix
 *          from `typename'. See (h) below for when `typename' is a pointer typedef.
 *      (f) If `typename' is a name of constrained pointer type ending with `_t',
 *          then `basetag' is formed by stripping the `_t' suffix from `typename'.
 *
 *      Additionally, constrained pointers to constrained const pointers are a
 *      special case:
 *
 *      (g) If `typename' is a name of a constrained pointer type, ending with
 *          `_{innertag}_t', and `typename' has `const' qualifier, then `basetag'
 *          is formed by replacing `_{innertag}_t' with `_c{innertag}'
 *
 *      Finally, sometimes `name_t' represents not `struct name' but `struct name *'.
 *      This creates additional special case:
 *
 *      (h) If `typename' is a pointer typedef named `{struct}_t`, such as
 *          `mbuf_t',  then creating a constrained pointer to a `typename' would
 *           require creating a  constrained pointer to an unconstrained pointer,
 *           which is not supported at the moment. Instead, a constrained pointer to
 *           `typeof(*typename)` must be created first, and constrained again. Using
 *           the `mbuf_t` example, first one should create a constrained pointer to
 *           `struct mbuf`, e.g, `mbuf_bptr_t`, and then constrain it again with
 *           `tag`, leading to `mbuf_bptr_ref_t'.
 *
 *      Examples:
 *
 *      (1) `int_ref_t' is a `reference pointer' to `int', following the rule (a) above.
 *      (2) `so_pru_ref_t' is a `reference pointer' to function `so_pru',
 *          following the rule (b) above.
 *      (3) `socket_ref_t' is a `reference pointer' to `struct socket',
 *          following the rule (c) above.
 *      (4) `classq_pkt_type_ref_t' is a `reference pointer' to `enum classq_pkt_type'
 *          following the rule (d) above.
 *      (5) `classq_pkt_type_ref_t' is a also `reference pointer' to `classq_pkt_type_t'
 *          following the rule (e) above.
 *      (6) `socket_ref_ref_t' is a `reference pointer' to `socket_ref_t`,
 *          following the rule (f) above.
 *      (7) `socket_cref_ref_t' is a `reference pointer' to `socket_ref_t const`,
 *          following the rule (g) above.
 *      (8) `mbuf_ref_ref_t', is a `reference pointer' to `mbuf_ref_t`, and is one
 *          possible result of creating a `reference pointer' to `mbuf_t',
 *          following the rule (h) above.
 *      (9) `mbuf_bptr_ref_t', is a `reference pointer' to `mbuf_bptr_t`, and
 *          is another possible result of creating a `reference pointer' to
 *          `mbuf_t', following the rule (h) above.
 *
 */

/*
 * Constraint contract constants.
 *
 * At the moment only clang (when compiled with `ptrcheck' feature) supports
 * pointer tagging via `__single', `__indexable' and `__bidi_indexable' attributes.
 *
 * During the transitional period, the `__indexable__' and `__bidi_indexable'
 * constraints will decay to raw pointers if the `ptrcheck' feature is not enabled.
 * Once the transitional period is over, the `__CCT_CONTRACT_ATTR_{B}PTR' constraints
 * will stop decaying to raw pointers when built by sufficiently recent version
 * of clang.
 *
 * Support for other compilers will be added after the introduction of support
 * for pointer tagging on those compilers.
 */
#if defined(__clang__)
#define __CCT_CONTRACT_ATTR_REF         __single
#define __CCT_CONTRACT_ATTR_CREF        const __single
#if  __has_ptrcheck
#define __CCT_CONTRACT_ATTR_BPTR        __bidi_indexable
#define __CCT_CONTRACT_ATTR_PTR         __indexable
#else /* __clang__ + __has_ptrcheck */
#define __CCT_CONTRACT_ATTR_BPTR
#define __CCT_CONTRACT_ATTR_PTR
#endif /* __clang__ + !__has_ptrcheck */
#else /* !__clang__ */
#define __CCT_CONTRACT_ATTR_REF
#define __CCT_CONTRACT_ATTR_CREF        const
#define __CCT_CONTRACT_ATTR_BPTR
#define __CCT_CONTRACT_ATTR_PTR
#endif /* __clang__ */

#define __CCT_CONTRACT_TAG_REF          _ref
#define __CCT_CONTRACT_TAG_CREF         _cref
#define __CCT_CONTRACT_TAG_BPTR         _bptr
#define __CCT_CONTRACT_TAG_PTR          _ptr

/* Helper macros */
#define __CCT_DEFER(F, ...) F(__VA_ARGS__)
#define __CCT_CONTRACT_TO_ATTR(kind) __CONCAT(__CCT_CONTRACT_ATTR_, kind)
#define __CCT_CONTRACT_TO_TAG(kind)  __CCT_DEFER(__CONCAT, __CCT_CONTRACT_TAG_, kind)

#define __CCT_COUNT_ARGS1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N
#define __CCT_COUNT_ARGS(...) \
	__CCT_COUNT_ARGS1(, __VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
#define __CCT_DISPATCH1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
#define __CCT_DISPATCH(base, ...) \
	__CCT_DISPATCH1(base, __CCT_COUNT_ARGS(__VA_ARGS__), __VA_ARGS__)

/* Covert a contract list to a type suffix */
#define __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_1(kind)                                                \
	__CCT_DEFER(__CONCAT, __CCT_CONTRACT_TO_TAG(kind), _t)
#define __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_2(kind1, kind2)                                        \
	__CCT_DEFER(__CONCAT, __CCT_CONTRACT_TO_TAG(kind1),                                             \
	         __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_1(kind2))
#define __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_3(kind1, kind2, kind3)                                 \
	__CCT_DEFER(__CONCAT, __CCT_CONTRACT_TO_TAG(kind1),                                             \
	         __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_2(kind2, kind3))

/* Create typedefs for the constrained pointer type */
#define __CCT_DECLARE_CONSTRAINED_PTR_TYPE_3(basetype, basetag, kind)                               \
typedef basetype * __CCT_CONTRACT_TO_ATTR(kind)                                                     \
	__CCT_DEFER(__CONCAT, basetag,  __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_1(kind))

#define __CCT_DECLARE_CONSTRAINED_PTR_TYPE_4(basetype, basetag, kind1, kind2)                       \
typedef basetype * __CCT_CONTRACT_TO_ATTR(kind1)                                                    \
	         * __CCT_CONTRACT_TO_ATTR(kind2)                                                        \
	__CCT_DEFER(__CONCAT, basetag,  __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_2(kind1, kind2))

#define __CCT_DECLARE_CONSTRAINED_PTR_TYPE_5(basetype, basetag, kind1, kind2, kind3)                \
typedef basetype * __CCT_CONTRACT_TO_ATTR(kind1)                                                    \
	         * __CCT_CONTRACT_TO_ATTR(kind2)                                                        \
	         * __CCT_CONTRACT_TO_ATTR(kind3)                                                        \
	__CCT_DEFER(__CONCAT, basetag,  __CCT_CONTRACT_LIST_TO_TAGGED_SUFFIX_3(kind1, kind2, kind3))

/*
 * Lower level type constructor.
 */
#define __CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, ...)                                  \
	__CCT_DISPATCH(__CCT_DECLARE_CONSTRAINED_PTR_TYPE, basetype, basetag, __VA_ARGS__)

/*
 * Higher level type constructors.
 * The constrained types that can potentially break the ABI are not exposed
 * into the user-space.
 */
#if defined(KERNEL)
#define __CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)                                      \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, REF);                                         \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, BPTR);                                        \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, PTR);                                         \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, REF, REF);                                    \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, REF, PTR);                                    \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, PTR, REF)
#else /* !defined(KERNEL) */
#define __CCT_DECLARE_CONSTRAINED_PTR_TYPES(basetype, basetag)                                      \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, REF);                                         \
__CCT_DECLARE_CONSTRAINED_PTR_TYPE(basetype, basetag, REF, REF)
#endif /* !defined(KERNEL) */

#endif /* __CONSTRAINED_CTYPES__ */