1 /*
2 ** cdecl -- C gibberish translator
3 ** src/c_type.h
4 **
5 ** Copyright (C) 2017-2021 Paul J. Lucas
6 **
7 ** This program is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifndef cdecl_c_type_H
22 #define cdecl_c_type_H
23
24 /**
25 * @file
26 * Declares constants, types, and functions for C/C++ types.
27 */
28
29 // local
30 #include "pjl_config.h" /* must go first */
31 #include "cdecl.h"
32 #include "c_lang.h"
33 #include "options.h"
34 #include "types.h"
35 #include "util.h"
36
37 /// @cond DOXYGEN_IGNORE
38
39 // standard
40 #include <assert.h>
41 #include <stdbool.h>
42 #include <inttypes.h> /* for PRIX64, etc. */
43
44 _GL_INLINE_HEADER_BEGIN
45 #ifndef C_TYPE_INLINE
46 # define C_TYPE_INLINE _GL_INLINE
47 #endif /* C_TYPE_INLINE */
48
49 /// @endcond
50
51 /**
52 * @defgroup c-types-group C/C++ Types
53 * Constants, types, and functions for C/C++ types.
54 * @{
55 */
56
57 ////////// types //////////////////////////////////////////////////////////////
58
59 /**
60 * The C/C++ type of an identifier (variable, function, etc.). A type is split
61 * into parts because the number of distinct bits needed in total exceeds 64.
62 */
63 struct c_type {
64 /**
65 * The base types (`int`, `double`, etc.) including user-defined types
66 * (`enum`, `struct`, etc.), modifiers (`short`, `unsigned`, etc.), and also
67 * `namespace` and the generic `scope` since it makes sense to store those
68 * with other scope-types (like `struct`).
69 *
70 * Constants for base types begin with `TB_`.
71 */
72 c_tid_t btids;
73
74 /**
75 * The storage classes (`extern`, `static`, etc., including `typedef`),
76 * storage-class-like things (`default`, `friend`, `inline`, etc.), and also
77 * qualifiers (`_Atomic`, `const`, etc.) and ref-qualifiers (`&`, `&&`).
78 *
79 * Constants for storage-class-like things begin with `TS_`.
80 */
81 c_tid_t stids;
82
83 /**
84 * Attributes.
85 *
86 * Constants for attributes begin with `TA_`.
87 */
88 c_tid_t atids;
89 };
90
91 /**
92 * Convenience macro for specifying a complete \ref c_type literal.
93 *
94 * @param BTID The base \ref c_tid_t.
95 * @param STID The storage \ref c_tid_t.
96 * @param ATID The attribute(s) \ref c_tid_t.
97 * @return Returns a reference to said literal.
98 *
99 * @sa #C_TYPE_LIT_A()
100 * @sa #C_TYPE_LIT_A_ANY()
101 * @sa #C_TYPE_LIT_B()
102 * @sa #C_TYPE_LIT_B_ANY()
103 * @sa #C_TYPE_LIT_S()
104 * @sa #C_TYPE_LIT_S_ANY()
105 */
106 #define C_TYPE_LIT(BTID,STID,ATID) \
107 (c_type_t const){ (BTID), (STID), (ATID) }
108
109 /**
110 * Convenience macro for specifying a \ref c_type literal from \a ATID.
111 *
112 * @param ATID The attribute(s) \ref c_tid_t.
113 * @return Returns a reference to said literal.
114 *
115 * @sa #C_TYPE_LIT()
116 * @sa #C_TYPE_LIT_A_ANY()
117 * @sa #C_TYPE_LIT_B()
118 * @sa #C_TYPE_LIT_B_ANY()
119 * @sa #C_TYPE_LIT_S()
120 * @sa #C_TYPE_LIT_S_ANY()
121 */
122 #define C_TYPE_LIT_A(ATID) \
123 C_TYPE_LIT( TB_NONE, TS_NONE, (ATID) )
124
125 /**
126 * Convenience macro for specifying a \ref c_type literal from #TB_ANY,
127 * #TS_ANY, and \a ATID.
128 *
129 * @param ATID The attribute(s) \ref c_tid_t.
130 * @return Returns a reference to said literal.
131 *
132 * @sa #C_TYPE_LIT()
133 * @sa #C_TYPE_LIT_A()
134 * @sa #C_TYPE_LIT_B()
135 * @sa #C_TYPE_LIT_B_ANY()
136 * @sa #C_TYPE_LIT_S()
137 * @sa #C_TYPE_LIT_S_ANY()
138 */
139 #define C_TYPE_LIT_A_ANY(ATID) \
140 C_TYPE_LIT( TB_ANY, TS_ANY, (ATID) )
141
142 /**
143 * Convenience macro for specifying a \ref c_type literal from \a BTID.
144 *
145 * @param BTID The base \ref c_tid_t.
146 * @return Returns a reference to said literal.
147 *
148 * @sa #C_TYPE_LIT()
149 * @sa #C_TYPE_LIT_A()
150 * @sa #C_TYPE_LIT_S()
151 */
152 #define C_TYPE_LIT_B(BTID) \
153 C_TYPE_LIT( (BTID), TS_NONE, TA_NONE )
154
155 /**
156 * Convenience macro for specifying a \ref c_type literal from \a BTID,
157 * #TS_ANY, and #TA_ANY.
158 *
159 * @param BTID The base \ref c_tid_t.
160 * @return Returns a reference to said literal.
161 *
162 * @sa #C_TYPE_LIT()
163 * @sa #C_TYPE_LIT_A()
164 * @sa #C_TYPE_LIT_A_ANY()
165 * @sa #C_TYPE_LIT_B()
166 * @sa #C_TYPE_LIT_S()
167 * @sa #C_TYPE_LIT_S_ANY()
168 */
169 #define C_TYPE_LIT_B_ANY(BTID) \
170 C_TYPE_LIT( (BTID), TS_ANY, TA_ANY )
171
172 /**
173 * Convenience macro for specifying a \ref c_type literal from \a STID.
174 *
175 * @param STID The storage \ref c_tid_t.
176 * @return Returns a reference to said literal.
177 *
178 * @sa #C_TYPE_LIT()
179 * @sa #C_TYPE_LIT_A()
180 * @sa #C_TYPE_LIT_A_ANY()
181 * @sa #C_TYPE_LIT_B()
182 * @sa #C_TYPE_LIT_B_ANY()
183 * @sa #C_TYPE_LIT_S_ANY()
184 */
185 #define C_TYPE_LIT_S(STID) \
186 C_TYPE_LIT( TB_NONE, (STID), TA_NONE )
187
188 /**
189 * Convenience macro for specifying a \ref c_type literal from #TB_ANY, \a
190 * STID, and #TA_ANY.
191 *
192 * @param STID The storage \ref c_tid_t.
193 * @return Returns a reference to said literal.
194 *
195 * @sa #C_TYPE_LIT()
196 * @sa #C_TYPE_LIT_A()
197 * @sa #C_TYPE_LIT_A_ANY()
198 * @sa #C_TYPE_LIT_B()
199 * @sa #C_TYPE_LIT_B_ANY()
200 * @sa #C_TYPE_LIT_S()
201 */
202 #define C_TYPE_LIT_S_ANY(STID) \
203 C_TYPE_LIT( TB_ANY, (STID), TA_ANY )
204
205 /**
206 * For \ref c_tid_t values, the low-order 4 bits specify the \ref c_tpid and
207 * thus how the value should be interpreted.
208 */
209 enum c_tpid {
210 //
211 // Type part IDs start at 1 so we know a c_tid_t value has been initialized
212 // properly as opposed to it being 0 by default.
213 //
214 C_TPID_NONE = 0u, ///< No types.
215 C_TPID_BASE = (1u << 0), ///< Base types, e.g., `int`.
216 C_TPID_STORE = (1u << 1), ///< Storage types, e.g., `static`.
217 C_TPID_ATTR = (1u << 2) ///< Attributes.
218 };
219
220 //
221 // The difference between TB_TYPEDEF and TS_TYPEDEF is that:
222 //
223 // * TS_TYPEDEF is the "storage class" for a declaration as a whole while it's
224 // being declared during parsing.
225 //
226 // * TB_TYPEDEF is the "type" for a particular typedef'd type, e.g., size_t,
227 // after parsing a declaration and the new type has been defined. Hence,
228 // TB_TYPEDEF is the somewhat unnecessary when the kind of an AST is
229 // K_TYPEDEF, but it has to have some type.
230 //
231
232 #define TX_NONE 0x0000000000000000ull /**< No type at all. */
233
234 // base types & modifiers
235 #define TB_NONE 0x0000000000000001ull /**< No base type. */
236 #define TB_ANY 0xFFFFFFFFFFFFFFF1ull /**< Any base type. */
237 #define TB_VOID 0x0000000000000011ull /**< `void` */
238 #define TB_AUTO 0x0000000000000021ull /**< C++11's `auto`. */
239 #define TB_BOOL 0x0000000000000041ull /**< `_Bool` or `bool` */
240 #define TB_CHAR 0x0000000000000081ull /**< `char` */
241 #define TB_CHAR8_T 0x0000000000000101ull /**< `char8_t` */
242 #define TB_CHAR16_T 0x0000000000000201ull /**< `char16_t` */
243 #define TB_CHAR32_T 0x0000000000000401ull /**< `char32_t` */
244 #define TB_WCHAR_T 0x0000000000000801ull /**< `wchar_t` */
245 #define TB_SHORT 0x0000000000001001ull /**< `short` */
246 #define TB_INT 0x0000000000002001ull /**< `int` */
247 #define TB_LONG 0x0000000000004001ull /**< `long` */
248 #define TB_LONG_LONG 0x0000000000008001ull /**< `long long` */
249 #define TB_SIGNED 0x0000000000010001ull /**< `signed` */
250 #define TB_UNSIGNED 0x0000000000020001ull /**< `unsigned` */
251 #define TB_FLOAT 0x0000000000040001ull /**< `float` */
252 #define TB_DOUBLE 0x0000000000080001ull /**< `double` */
253 #define TB_COMPLEX 0x0000000000100001ull /**< `_Complex` */
254 #define TB_IMAGINARY 0x0000000000200001ull /**< `_Imaginary` */
255 #define TB_ENUM 0x0000000000400001ull /**< `enum` */
256 #define TB_STRUCT 0x0000000000800001ull /**< `struct` */
257 #define TB_UNION 0x0000000001000001ull /**< `union` */
258 #define TB_CLASS 0x0000000002000001ull /**< `class` */
259 #define TB_NAMESPACE 0x0000000004000001ull /**< `namespace` */
260 #define TB_SCOPE 0x0000000008000001ull /**< Generic scope. */
261 #define TB_TYPEDEF 0x0000000010000001ull /**< E.g., `size_t` */
262
263 // Embedded C types & modifiers
264 #define TB_EMC_ACCUM 0x0000000020000001ull /**< `_Accum` */
265 #define TB_EMC_FRACT 0x0000000040000001ull /**< `_Fract` */
266 #define TB_EMC_SAT 0x0000000080000001ull /**< `_Sat` */
267
268 // storage classes
269 #define TS_NONE 0x0000000000000002ull /**< No storage type. */
270 #define TS_ANY 0xFFFFFFFFFFFFFFF2ull /**< Any storage type. */
271 #define TS_AUTO 0x0000000000000012ull /**< C's `auto`. */
272 #define TS_APPLE_BLOCK 0x0000000000000022ull /**< Block. */
273 #define TS_EXTERN 0x0000000000000042ull /**< `extern` */
274 #define TS_EXTERN_C 0x0000000000000082ull /**< `extern "C"` */
275 #define TS_MUTABLE 0x0000000000000102ull /**< `mutable` */
276 #define TS_REGISTER 0x0000000000000202ull /**< `register` */
277 #define TS_STATIC 0x0000000000000402ull /**< `static` */
278 #define TS_THREAD_LOCAL 0x0000000000000802ull /**< `thread_local` */
279 #define TS_TYPEDEF 0x0000000000001002ull /**< `typedef` or `using` */
280
281 // storage-class-like
282 #define TS_CONSTEVAL 0x0000000000002002ull /**< `consteval` */
283 #define TS_CONSTEXPR 0x0000000000004002ull /**< `constexpr` */
284 #define TS_CONSTINIT 0x0000000000008002ull /**< `constinit` */
285 #define TS_DEFAULT 0x0000000000010002ull /**< `= default` */
286 #define TS_DELETE 0x0000000000020002ull /**< `= delete` */
287 #define TS_EXPLICIT 0x0000000000040002ull /**< `explicit` */
288 #define TS_EXPORT 0x0000000000080002ull /**< `export` */
289 #define TS_FINAL 0x0000000000100002ull /**< `final` */
290 #define TS_FRIEND 0x0000000000200002ull /**< `friend` */
291 #define TS_INLINE 0x0000000000400002ull /**< `inline` */
292 #define TS_NOEXCEPT 0x0000000000800002ull /**< `noexcept` */
293 #define TS_OVERRIDE 0x0000000001000002ull /**< `override` */
294 #define TS_PURE_VIRTUAL 0x0000000002000002ull /**< `= 0` */
295 #define TS_THROW 0x0000000004000002ull /**< `throw()` */
296 #define TS_VIRTUAL 0x0000000008000002ull /**< `virtual` */
297
298 // qualifiers
299 #define TS_ATOMIC 0x0000000010000002ull /**< `_Atomic` */
300 #define TS_CONST 0x0000000020000002ull /**< `const` */
301 #define TS_RESTRICT 0x0000000040000002ull /**< `restrict` */
302 #define TS_VOLATILE 0x0000000080000002ull /**< `volatile` */
303
304 // Unified Parallel C qualifiers
305 #define TS_UPC_RELAXED 0x0000000100000002ull /**< `relaxed` */
306 #define TS_UPC_SHARED 0x0000000200000002ull /**< `shared` */
307 #define TS_UPC_STRICT 0x0000000400000002ull /**< `strict` */
308
309 // ref-qualifiers
310 #define TS_REFERENCE 0x0000000800000002ull /**< `void f() &` */
311 #define TS_RVALUE_REFERENCE 0x0000001000000002ull /**< `void f() &&` */
312
313 // attributes
314 #define TA_NONE 0x0000000000000004ull /**< No attribute. */
315 #define TA_ANY 0xFFFFFFFFFFFFFFF4ull /**< Any attribute. */
316 #define TA_CARRIES_DEPENDENCY 0x0000000000000014ull /**< `carries_dependency` */
317 #define TA_DEPRECATED 0x0000000000000024ull /**< `deprecated` */
318 #define TA_MAYBE_UNUSED 0x0000000000000044ull /**< `maybe_unused` */
319 #define TA_NODISCARD 0x0000000000000084ull /**< `nodiscard` */
320 #define TA_NORETURN 0x0000000000000104ull /**< `noreturn` */
321 #define TA_NO_UNIQUE_ADDRESS 0x0000000000000204ull /**< `no_unique_address` */
322
323 // Microsoft calling conventions
324 #define TA_MSC_CDECL 0x0000000000001004ull /**< `__cdecl` */
325 #define TA_MSC_CLRCALL 0x0000000000002004ull /**< `__clrcall` */
326 #define TA_MSC_FASTCALL 0x0000000000004004ull /**< `__fastcall` */
327 #define TA_MSC_STDCALL 0x0000000000008004ull /**< `__stdcall` */
328 #define TA_MSC_THISCALL 0x0000000000010004ull /**< `__thiscall` */
329 #define TA_MSC_VECTORCALL 0x0000000000020004ull /**< `__vectorcall` */
330
331 // bit masks
332 #define TX_MASK_TPID 0x000000000000000Full /**< Type part ID bitmask.*/
333 #define TS_MASK_STORAGE 0x000000000FFFFFF2ull /**< Storage bitmask. */
334 #define TS_MASK_QUALIFIER 0x00000007F0000002ull /**< Qualifier bitmask. */
335 #define TS_MASK_REF_QUALIFIER 0x0000001800000002ull /**< Ref-qual bitmask. */
336
337 extern c_type_t const T_NONE; ///< No type.
338 extern c_type_t const T_ANY; ///< All types.
339 extern c_type_t const T_ANY_CONST_CLASS;///< Any `const` `class`-like type.
340 extern c_type_t const T_TS_TYPEDEF; ///< Type containing only #TS_TYPEDEF.
341
342 // shorthands
343
344 /// Shorthand for any character type.
345 #define TB_ANY_CHAR ( TB_CHAR | TB_WCHAR_T \
346 | TB_CHAR8_T | TB_CHAR16_T | TB_CHAR32_T )
347
348 /// Shorthand for `class`, `struct`, or `union`.
349 #define TB_ANY_CLASS ( TB_CLASS | TB_STRUCT | TB_UNION )
350
351 /// Shorthand for any Embedded C type.
352 #define TB_ANY_EMC ( TB_EMC_ACCUM | TB_EMC_FRACT )
353
354 /// Shorthand for any floating-point type.
355 #define TB_ANY_FLOAT ( TB_FLOAT | TB_DOUBLE )
356
357 /// Shorthand for any integral type.
358 #define TB_ANY_INTEGRAL ( TB_BOOL | TB_ANY_CHAR | TB_INT \
359 | TB_ANY_MODIFIER )
360
361 /// Shorthand for an any modifier.
362 #define TB_ANY_MODIFIER ( TB_SHORT | TB_LONG | TB_LONG_LONG | TB_SIGNED \
363 | TB_UNSIGNED )
364
365 /// Shorthand for any Microsoft C/C++ calling convention.
366 #define TA_ANY_MSC_CALL ( TA_MSC_CDECL | TA_MSC_CLRCALL \
367 | TA_MSC_FASTCALL | TA_MSC_STDCALL \
368 | TA_MSC_THISCALL | TA_MSC_VECTORCALL )
369
370 /// Shorthand for `class`, `struct`, `union`, or `namespace`.
371 #define TB_ANY_SCOPE ( TB_ANY_CLASS | TB_NAMESPACE )
372
373 /// Shorthand for any reference qualifier.
374 #define TS_ANY_REFERENCE ( TS_REFERENCE | TS_RVALUE_REFERENCE )
375
376 /// Shorthand for `const` or `volatile`.
377 #define TS_CV ( TS_CONST | TS_VOLATILE )
378
379 /// Shorthand for `const`, `volatile`, or `restrict`.
380 #define TS_CVR ( TS_CV | TS_RESTRICT )
381
382 /**
383 * The only types that can apply to in-class constructor declarations.
384 *
385 * @sa #TS_CONSTRUCTOR_DEF
386 * @sa #TS_CONSTRUCTOR_ONLY
387 * @sa #TS_FUNC_LIKE_CPP
388 */
389 #define TS_CONSTRUCTOR_DECL ( TS_CONSTEXPR | TS_DEFAULT | TS_DELETE \
390 | TS_EXPLICIT | TS_FRIEND | TS_INLINE \
391 | TS_NOEXCEPT | TS_THROW )
392
393 /**
394 * A subset of #TS_CONSTRUCTOR_DECL that can apply to file-scope constructor
395 * definitions.
396 *
397 * @sa #TS_CONSTRUCTOR_DECL
398 */
399 #define TS_CONSTRUCTOR_DEF ( TS_CONSTEXPR | TS_INLINE | TS_NOEXCEPT \
400 | TS_THROW )
401
402 /**
403 * The types that can apply only to constructors.
404 *
405 * @sa #TS_CONSTRUCTOR_DECL
406 * @sa #TS_CONSTRUCTOR_DEF
407 */
408 #define TS_CONSTRUCTOR_ONLY TS_EXPLICIT
409
410 /**
411 * The only types that can apply to in-class destructor declarations.
412 *
413 * @sa #TS_CONSTRUCTOR_DECL
414 * @sa #TS_DESTRUCTOR_DEF
415 */
416 #define TS_DESTRUCTOR_DECL ( TS_DEFAULT | TS_DELETE | TS_FINAL | TS_FRIEND \
417 | TS_INLINE | TS_NOEXCEPT | TS_OVERRIDE \
418 | TS_PURE_VIRTUAL | TS_THROW | TS_VIRTUAL )
419
420 /**
421 * A subset of #TS_DESTRUCTOR_DECL that can apply to file-scope destructor
422 * definitions.
423 *
424 * @sa #TS_DESTRUCTOR_DECL
425 */
426 #define TS_DESTRUCTOR_DEF ( TS_INLINE | TS_NOEXCEPT | TS_THROW )
427
428 /**
429 * The only storage-types that can apply to C functions.
430 *
431 * @sa #TS_FUNC_LIKE_CPP
432 * @sa #TS_MAIN_FUNC_C
433 */
434 #define TS_FUNC_C ( TS_EXTERN | TS_INLINE | TS_STATIC | TS_TYPEDEF )
435
436 /**
437 * The only storage-types that can apply to C++ function-like things
438 * (functions, blocks, constructors, destructors, operators, and user-defined
439 * conversion operators and literals).
440 *
441 * @sa #TS_CONSTRUCTOR_DECL
442 * @sa #TS_CONSTRUCTOR_DEF
443 * @sa #TS_MAIN_FUNC_CPP
444 * @sa #TS_NEW_DELETE_OPER
445 * @sa #TS_USER_DEF_CONV
446 */
447 #define TS_FUNC_LIKE_CPP ( TS_CV | TS_CONSTEVAL | TS_CONSTEXPR \
448 | TS_DEFAULT | TS_DELETE | TS_EXPLICIT \
449 | TS_EXPORT | TS_EXTERN_C | TS_FINAL \
450 | TS_FRIEND | TS_FUNC_C | TS_NOEXCEPT \
451 | TS_OVERRIDE | TS_PURE_VIRTUAL \
452 | TS_ANY_REFERENCE | TS_RESTRICT | TS_THROW \
453 | TS_TYPEDEF | TS_VIRTUAL )
454
455 /**
456 * The only storage types that can apply to a C program's `main()` function.
457 *
458 * @sa #TS_FUNC_C
459 * @sa #TS_MAIN_FUNC_CPP
460 */
461 #define TS_MAIN_FUNC_C TS_EXTERN
462
463 /**
464 * The only types that can apply to a C++ program's `main()` function.
465 *
466 * @sa #TS_FUNC_LIKE_CPP
467 * @sa #TS_MAIN_FUNC_C
468 */
469 #define TS_MAIN_FUNC_CPP ( TS_EXTERN | TS_FRIEND | TS_NOEXCEPT | TS_THROW )
470
471 /**
472 * The types that can apply only to member functions, operators, or user-
473 * defined conversions operators.
474 *
475 * @sa #TS_FUNC_LIKE_CPP
476 * @sa #TS_NONMEMBER_FUNC_ONLY
477 */
478 #define TS_MEMBER_FUNC_ONLY ( TS_CV \
479 | (opt_lang < LANG_CPP_20 ? TS_DEFAULT : TS_NONE)\
480 | TS_DELETE | TS_FINAL | TS_OVERRIDE \
481 | TS_ANY_REFERENCE | TS_RESTRICT | TS_VIRTUAL )
482
483 /**
484 * The only types that can apply to operators `new`, `new[]`, `delete`, or
485 * `delete[]`.
486 *
487 * @sa #TS_FUNC_LIKE_CPP
488 */
489 #define TS_NEW_DELETE_OPER ( TS_EXTERN | TS_FRIEND | TS_NOEXCEPT \
490 | TS_STATIC | TS_THROW )
491
492 /**
493 * The types that can apply only to non-member functions or operators.
494 *
495 * @sa #TS_MEMBER_FUNC_ONLY
496 */
497 #define TS_NONMEMBER_FUNC_ONLY TS_FRIEND
498
499 /**
500 * The types that can apply only to function-like things except constructors.
501 *
502 * @sa #TS_CONSTRUCTOR_DECL
503 * @sa #TS_CONSTRUCTOR_DEF
504 * @sa #TS_CONSTRUCTOR_ONLY
505 * @sa #TS_FUNC_LIKE_CPP
506 */
507 #define TS_NOT_CONSTRUCTOR ( TS_CV | TS_EXTERN | TS_EXTERN_C | TS_FINAL \
508 | TS_OVERRIDE | TS_ANY_REFERENCE | TS_RESTRICT \
509 | TS_STATIC | TS_VIRTUAL )
510
511 /**
512 * The only types that can apply to user-defined conversion operators.
513 *
514 * @sa #TS_FUNC_LIKE_CPP
515 */
516 #define TS_USER_DEF_CONV ( TS_CONST | TS_CONSTEXPR | TS_EXPLICIT \
517 | TS_FINAL | TS_FRIEND | TS_INLINE \
518 | TS_NOEXCEPT | TS_OVERRIDE | TS_PURE_VIRTUAL \
519 | TS_THROW | TS_VIRTUAL )
520
521 /**
522 * Hexadecimal print conversion specifier for \ref c_tid_t.
523 */
524 #define PRIX_C_TID_T PRIX64
525
526 ////////// extern functions ///////////////////////////////////////////////////
527
528 /**
529 * Adds a type to an existing type, e.g., `short` to `int`, ensuring that a
530 * particular type is never added more than once, e.g., `short` to `short int`.
531 *
532 * A special case has to be made for `long` to allow for `long long` yet not
533 * allow for `long long long`.
534 *
535 * @param dst_tids The \ref c_tid_t to add to.
536 * @param new_tids The \ref c_tid_t to add.
537 * @param new_loc The source location of \a new_id.
538 * @return Returns `true` only if the type added successfully.
539 *
540 * @sa c_type_add(()
541 */
542 PJL_WARN_UNUSED_RESULT
543 bool c_tid_add( c_tid_t *dst_tids, c_tid_t new_tids, c_loc_t const *new_loc );
544
545 /**
546 * Gets the C/C++ name of \a tids.
547 *
548 * @param tids The \ref c_tid_t to get the name of.
549 * @return Returns said name.
550 *
551 * @warning The pointer returned is to a small number of static buffers, so you
552 * can't do something like call this more than twice in the same `printf()`
553 * statement.
554 *
555 * @sa c_tid_name_english()
556 * @sa c_tid_name_error()
557 * @sa c_type_name_c()
558 */
559 PJL_WARN_UNUSED_RESULT
560 char const* c_tid_name_c( c_tid_t tids );
561
562 /**
563 * Gets the pseudo-English name of \a tids, if available; the C/C++ name if
564 * not.
565 *
566 * @param tids The \ref c_tid_t to get the name of.
567 * @return Returns said name.
568 *
569 * @warning The pointer returned is to a small number of static buffers, so you
570 * can't do something like call this more than twice in the same `printf()`
571 * statement.
572 *
573 * @sa c_tid_name_c()
574 * @sa c_tid_name_error()
575 * @sa c_type_name_english()
576 */
577 PJL_WARN_UNUSED_RESULT
578 char const* c_tid_name_english( c_tid_t tids );
579
580 /**
581 * Gets the name of \a tids for part of an error message. If translating from
582 * pseudo-English to gibberish and the type has an pseudo-English alias, return
583 * the alias, e.g., `non-returning` rather than `noreturn`.
584 *
585 * @param tids The \ref c_tid_t to get the name of.
586 * @return Returns said name.
587 *
588 * @warning The pointer returned is to a small number of static buffers, so you
589 * can't do something like call this more than twice in the same `printf()`
590 * statement.
591 *
592 * @sa c_tid_name_c()
593 * @sa c_tid_name_english()
594 * @sa c_type_name_error()
595 */
596 PJL_WARN_UNUSED_RESULT
597 char const* c_tid_name_error( c_tid_t tids );
598
599 /**
600 * "Normalize" \a tids:
601 *
602 * 1. If it's #TB_SIGNED and not #TB_CHAR, remove #TB_SIGNED. If it becomes
603 * #TB_NONE, make it #TB_INT.
604 * 2. If it's only implicitly #TB_INT (e.g., `unsigned`), make it explicitly
605 * #TB_INT (e.g., `unsigned int`).
606 *
607 * @param tids The \ref c_tid_t to normalize.
608 * @return Returns the normalized \ref c_tid_t.
609 */
610 PJL_WARN_UNUSED_RESULT
611 c_tid_t c_tid_normalize( c_tid_t tids );
612
613 /**
614 * Gets the "order" value of a \ref c_tid_t so it can be compared by its order.
615 * The order is:
616 *
617 * + { _none_ | `scope` } < [`inline`] `namespace` <
618 * { `struct` | `union` | `class` } <
619 * `enum` [`class`]
620 *
621 * I.e., the order of T1 ≤ T2 only if T1 can appear to the left (<) of T2
622 * in a declaration. For example, given:
623 * ```
624 * namespace N { class C { // ...
625 * ```
626 * order(`N`) ≤ order(`C`) because `N` can appear to the left of `C` in a
627 * declaration. However, given:
628 * ```
629 * class D { namespace M { // ...
630 * ```
631 * order(`D`) > order(`M`) and so `D` can not appear to the left of `M`.
632 *
633 * @param btids The scope-type ID to get the order of.
634 * @return Returns said order.
635 *
636 * @note The return value by itself is meaningless. All that matters is the
637 * result of comparing two orders.
638 */
639 PJL_WARN_UNUSED_RESULT
640 unsigned c_tid_scope_order( c_tid_t btids );
641
642 /**
643 * Gets the \ref c_tpid_t from \a tids.
644 *
645 * @param tids The type ID.
646 * @return Returns said \ref c_tpid_t.
647 *
648 * @sa c_tid_no_tpid()
649 */
650 PJL_WARN_UNUSED_RESULT
651 c_tpid_t c_tid_tpid( c_tid_t tids );
652
653 /**
654 * Adds a type to an existing type, e.g., `short` to `int`, ensuring that a
655 * particular type is never added more than once, e.g., `short` to `short int`.
656 *
657 * A special case has to be made for `long` to allow for `long long` yet not
658 * allow for `long long long`.
659 *
660 * @param dst_type The \ref c_type to add to.
661 * @param new_type The \ref c_type to add.
662 * @param new_loc The source location of \a new_type.
663 * @return Returns `true` only if \a new_type added successfully.
664 *
665 * @sa c_tid_add(()
666 * @sa c_type_add_tid()
667 * @sa c_type_or_eq()
668 */
669 PJL_WARN_UNUSED_RESULT
670 bool c_type_add( c_type_t *dst_type, c_type_t const *new_type,
671 c_loc_t const *new_loc );
672
673 /**
674 * Adds \a new_tids to \a dst_type.
675 *
676 * @param dst_type The \ref c_type to add to.
677 * @param new_tids The \ref c_tid_t to add.
678 * @param new_loc The source location of \a new_tids.
679 * @return Returns `true` only if \a new_tids added successfully.
680 *
681 * @sa c_type_add()
682 */
683 PJL_WARN_UNUSED_RESULT
684 bool c_type_add_tid( c_type_t *dst_type, c_tid_t new_tids,
685 c_loc_t const *new_loc );
686
687 /**
688 * Performs the bitwise-and of all the parts of \a i_type and \a j_type.
689 *
690 * @param i_type The first \ref c_type.
691 * @param j_type The second \ref c_type.
692 * @return Returns the resultant \ref c_type.
693 *
694 * @sa c_type_and_eq_compl()
695 * @sa c_type_or()
696 */
697 PJL_WARN_UNUSED_RESULT
698 c_type_t c_type_and( c_type_t const *i_type, c_type_t const *j_type );
699
700 /**
701 * Performs the bitwise-and of all the parts of \a dst_type with the complement
702 * of \a rm_type and stores the result in \a dst_type.
703 *
704 * @param dst_type The type to modify.
705 * @param rm_type The type to remove from \a dst_type.
706 *
707 * @sa c_type_or_eq()
708 */
709 void c_type_and_eq_compl( c_type_t *dst_type, c_type_t const *rm_type );
710
711 /**
712 * Checks that \a type is valid.
713 *
714 * @param type The \ref c_type to check.
715 * @return Returns the bitwise-or of the language(s) \a type is legal in.
716 */
717 PJL_WARN_UNUSED_RESULT
718 c_lang_id_t c_type_check( c_type_t const *type );
719
720 /**
721 * Checks whether \a i_type and \a j_type are equal.
722 *
723 * @param i_type The first \ref c_type.
724 * @param j_type The second \ref c_type.
725 * @return Returns `true` only if \a i_type equals \a j_type.
726 *
727 * @sa c_type_is_none()
728 */
729 PJL_WARN_UNUSED_RESULT
730 bool c_type_equal( c_type_t const *i_type, c_type_t const *j_type );
731
732 /**
733 * Creates a \ref c_type based on the type part ID of \a tids.
734 *
735 * @param tids The \ref c_tid_t to create the \ref c_type from.
736 * @return Returns said \ref c_type.
737 */
738 PJL_WARN_UNUSED_RESULT
739 c_type_t c_type_from_tid( c_tid_t tids );
740
741 /**
742 * Gets the \ref c_tid_t of \a type that corresponds to the type part ID of \a
743 * tids.
744 *
745 * @param type The \ref c_type to get the relevant \ref c_tid_t of.
746 * @param tids The \ref c_tid_t that specifies the part of \a type to get the
747 * pointer to.
748 * @return Returns the corresponding \ref c_tid_t of \a type for the part of \a
749 * tids.
750 *
751 * @sa c_type_get_tid_ptr()
752 */
753 PJL_WARN_UNUSED_RESULT
754 c_tid_t c_type_get_tid( c_type_t const *type, c_tid_t tids );
755
756 /**
757 * Gets a pointer to the \ref c_tid_t of \a type that corresponds to the type
758 * part ID of \a tids.
759 *
760 * @param type The \ref c_type to get a pointer to the relevant \ref c_tid_t
761 * of.
762 * @param tids The \ref c_tid_t that specifies the part of \a type to get the
763 * pointer to.
764 * @return Returns a pointer to the corresponding \ref c_tid_t of \a type for
765 * the part of \a tids.
766 *
767 * @sa c_type_get_tid()
768 */
769 PJL_WARN_UNUSED_RESULT
770 c_tid_t* c_type_get_tid_ptr( c_type_t *type, c_tid_t tids );
771
772 /**
773 * For all type part IDs of \a j_type that are not none, gets whether the
774 * corresponding type part ID of \a i_type is any of them.
775 *
776 * @param i_type The first \ref c_type.
777 * @param j_type The second \ref c_type.
778 * @return Returns `true` only if \a i_type contains any \a j_type.
779 *
780 * @sa c_tid_is_any()
781 */
782 PJL_WARN_UNUSED_RESULT
783 bool c_type_is_any( c_type_t const *i_type, c_type_t const *j_type );
784
785 /**
786 * Gets the C/C++ name of \a type.
787 *
788 * @param type The type to get the name for.
789 * @return Returns said name.
790 *
791 * @warning The pointer returned is to a small number of static buffers, so you
792 * can't do something like call this more than twice in the same `printf()`
793 * statement.
794 *
795 * @sa c_tid_name_c()
796 * @sa c_type_name_ecsu()
797 * @sa c_type_name_english()
798 * @sa c_type_name_error()
799 */
800 PJL_WARN_UNUSED_RESULT
801 char const* c_type_name_c( c_type_t const *type );
802
803 /**
804 * Gets the the C/C++ name for an `enum`, `struct`, `class`, or `union`.
805 *
806 * @param type The type to get the name for.
807 * @return Returns said name.
808 *
809 * @warning The pointer returned is to a small number of static buffers, so you
810 * can't do something like call this more than twice in the same `printf()`
811 * statement.
812 *
813 * @sa c_type_name_c()
814 * @sa c_type_name_english()
815 * @sa c_type_name_error()
816 */
817 PJL_WARN_UNUSED_RESULT
818 char const* c_type_name_ecsu( c_type_t const *type );
819
820 /**
821 * Gets the pseudo-English name of \a type, if available; the C/C++ name if
822 * not.
823 *
824 * @param type The type to get the name for.
825 * @return Returns said name.
826 *
827 * @warning The pointer returned is to a small number of static buffers, so you
828 * can't do something like call this more than twice in the same `printf()`
829 * statement.
830 *
831 * @sa c_tid_name_error()
832 * @sa c_type_name_c()
833 * @sa c_type_name_ecsu()
834 * @sa c_type_name_error()
835 */
836 PJL_WARN_UNUSED_RESULT
837 char const* c_type_name_english( c_type_t const *type );
838
839 /**
840 * Gets the name of \a type for part of an error message. If translating
841 * from pseudo-English to gibberish and the type has a pseudo-English alias,
842 * return the alias, e.g., `non-returning` rather than `noreturn`.
843 *
844 * @param type The type to get the name for.
845 * @return Returns said name.
846 *
847 * @warning The pointer returned is to a small number of static buffers, so you
848 * can't do something like call this more than twice in the same `printf()`
849 * statement.
850 *
851 * @sa c_type_name_c()
852 * @sa c_type_name_ecsu()
853 * @sa c_type_name_english()
854 */
855 PJL_WARN_UNUSED_RESULT
856 char const* c_type_name_error( c_type_t const *type );
857
858 /**
859 * Performs the bitwise-or of \a i_type and \a j_type.
860 *
861 * @param i_type The first type.
862 * @param j_type The second type.
863 * @return Returns the bitwise-or of \a i_type and \a j_type.
864 *
865 * @sa c_type_and()
866 * @sa c_type_and_eq_compl()
867 * @sa c_type_or_eq()
868 */
869 PJL_WARN_UNUSED_RESULT
870 c_type_t c_type_or( c_type_t const *i_type, c_type_t const *j_type );
871
872 /**
873 * Performs the bitwise-or of \a dst_type with \a add_type and stores the
874 * result in \a dst_type.
875 * @note Unlike c_type_add(), no checks are made.
876 *
877 * @param dst_type The type to modify.
878 * @param add_type The source type.
879 *
880 * @sa c_type_add()
881 * @sa c_type_and_eq_compl()
882 * @sa c_type_or()
883 */
884 void c_type_or_eq( c_type_t *dst_type, c_type_t const *add_type );
885
886 ////////// inline functions ///////////////////////////////////////////////////
887
888 /**
889 * Checks that the type part ID of \a tids is \a tpid.
890 *
891 * @param tids The \ref c_tid_t to check.
892 * @param tpid The \ref c_tpid_t to check against.
893 * @return Returns \a tids.
894 */
895 C_TYPE_INLINE PJL_NOWARN_UNUSED_RESULT
c_tid_check(c_tid_t tids,c_tpid_t tpid)896 c_tid_t c_tid_check( c_tid_t tids, c_tpid_t tpid ) {
897 assert( (tids & TX_MASK_TPID) == tpid );
898 return tids;
899 }
900
901 /**
902 * Checks whether \a tids has been complemented via `~`.
903 *
904 * @param tids The \ref c_tid_t to check.
905 * @return Returns `true` only if \a tids has been complemented.
906 *
907 * @sa c_tid_compl()
908 */
909 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_is_compl(c_tid_t tids)910 bool c_tid_is_compl( c_tid_t tids ) {
911 //
912 // The low-order 4 bits specify the c_tpid. Currently, type part IDs are 1
913 // (0b0001), 2 (0b0010), and 4 (0b0100). If tids is 0b1xxx, it means that it
914 // was complemented.
915 //
916 return (tids & 0x8) != 0;
917 }
918
919 /**
920 * Bitwise-complements \a tids. The `~` operator can't be used alone because
921 * the part ID of \a tids would be complemented also. This function
922 * complements \a tids while preserving the original part ID.
923 *
924 * @param tids The \ref c_tid_t to complement.
925 * @return Returns \a tids complemented.
926 *
927 * @sa c_tid_is_compl()
928 */
929 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_compl(c_tid_t tids)930 c_tid_t c_tid_compl( c_tid_t tids ) {
931 assert( !c_tid_is_compl( tids ) );
932 return ~tids ^ TX_MASK_TPID;
933 }
934
935 /**
936 * Checks whether \a tids is all of \a is_tids but not also any one of \a
937 * except_tids.
938 *
939 * @param tids The \ref c_tid_t to check.
940 * @param is_tids The bitwise-or of \ref c_tid_t to check for.
941 * @param except_tids The bitwise-or of \ref c_tid_t to exclude.
942 * @return Returns `true` only if \a tids contains any of \a is_tids, but not
943 * any of \a except_tids.
944 */
945 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_is_except(c_tid_t tids,c_tid_t is_tids,c_tid_t except_tids)946 bool c_tid_is_except( c_tid_t tids, c_tid_t is_tids, c_tid_t except_tids ) {
947 return (tids & (is_tids | except_tids)) == is_tids;
948 }
949
950 /**
951 * Gets the type ID value without the part ID.
952 *
953 * @param tids The \ref c_tid_t to get the value of.
954 * @return Returns the type ID value without the part ID.
955 *
956 * @sa c_tid_tpid()
957 */
958 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_no_tpid(c_tid_t tids)959 c_tid_t c_tid_no_tpid( c_tid_t tids ) {
960 return tids & ~TX_MASK_TPID;
961 }
962
963 /**
964 * Gets whether \a i_tids contains any of \a j_tids.
965 *
966 * @param i_tids The first \ref c_tid_t.
967 * @param j_tids The second \ref c_tid_t.
968 * @return Returns `true` only if \a i_tids contains any \a j_tids.
969 *
970 * @sa c_type_is_any()
971 */
972 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_is_any(c_tid_t i_tids,c_tid_t j_tids)973 bool c_tid_is_any( c_tid_t i_tids, c_tid_t j_tids ) {
974 assert( c_tid_tpid( i_tids ) == c_tid_tpid( j_tids ) );
975 return c_tid_no_tpid( i_tids & j_tids ) != TX_NONE;
976 }
977
978 /**
979 * Checks whether \a tids is "none."
980 *
981 * @note This function is useful only when the part ID of \a tids can be any
982 * part ID.
983 * @param tids The \ref c_tid_t to check.
984 * @return Returns `true` only if \a tids is `Tx_NONE`.
985 *
986 * @sa c_type_is_none()
987 */
988 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_is_none(c_tid_t tids)989 bool c_tid_is_none( c_tid_t tids ) {
990 return c_tid_no_tpid( tids ) == TX_NONE;
991 }
992
993 /**
994 * Checks if \a tids is equivalent to `size_t`.
995 *
996 * @note
997 * In cdecl, `size_t` is `typedef`d to be `unsigned long` in `c_typedef.c`.
998 *
999 * @param tids The \ref c_tid_t to check.
1000 * @return Returns `true` only if \a tids is `size_t`.
1001 *
1002 * @sa c_ast_is_size_t()
1003 */
1004 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_tid_is_size_t(c_tid_t tids)1005 bool c_tid_is_size_t( c_tid_t tids ) {
1006 assert( (tids & TX_MASK_TPID) == C_TPID_BASE );
1007 return (tids & c_tid_compl( TB_INT )) == (TB_UNSIGNED | TB_LONG);
1008 }
1009
1010 /**
1011 * Checks whether \a type is T_NONE.
1012 *
1013 * @param type The \ref c_type to check.
1014 * @return Returns `true` only if \a type is none.
1015 *
1016 * @sa c_type_equal()
1017 */
1018 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_type_is_none(c_type_t const * type)1019 bool c_type_is_none( c_type_t const *type ) {
1020 return c_type_equal( type, &T_NONE );
1021 }
1022
1023 /**
1024 * Checks whether the relevant \ref c_tid_t of \a type is any of \a tids.
1025 *
1026 * @param type The \ref c_type to check.
1027 * @param tids The \ref c_tid_t to check against.
1028 * @return Returns `true` only if the relevant \ref c_tid_t of \a type contains
1029 * any of \a tids.
1030 */
1031 C_TYPE_INLINE PJL_WARN_UNUSED_RESULT
c_type_is_tid_any(c_type_t const * type,c_tid_t tids)1032 bool c_type_is_tid_any( c_type_t const *type, c_tid_t tids ) {
1033 return c_tid_is_any( c_type_get_tid( type, tids ), tids );
1034 }
1035
1036 ///////////////////////////////////////////////////////////////////////////////
1037
1038 /** @} */
1039
1040 _GL_INLINE_HEADER_END
1041
1042 #endif /* cdecl_c_type_H */
1043 /* vim:set et sw=2 ts=2: */
1044