1 /*
2 ** cdecl -- C gibberish translator
3 ** src/c_type.c
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 /**
22 * @file
23 * Defines functions for C/C++ types.
24 */
25
26 // local
27 #include "pjl_config.h" /* must go first */
28 /// @cond DOXYGEN_IGNORE
29 #define C_TYPE_INLINE _GL_EXTERN_INLINE
30 /// @endcond
31 #include "c_type.h"
32 #include "c_lang.h"
33 #include "cdecl.h"
34 #include "gibberish.h"
35 #include "literals.h"
36 #include "options.h"
37 #include "print.h"
38 #include "strbuf.h"
39 #include "util.h"
40
41 /// @cond DOXYGEN_IGNORE
42
43 // standard
44 #include <assert.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #define C_TYPE_CHECK(...) BLOCK( \
49 c_lang_id_t const lang_ids = __VA_ARGS__; \
50 if ( lang_ids != LANG_ANY ) \
51 return lang_ids; )
52
53 #define C_TID_CHECK_COMBO(TID,TINFO,OK_TYPE_LANGS) C_TYPE_CHECK( \
54 c_tid_check_combo( (TID), (TINFO), ARRAY_SIZE(TINFO), (OK_TYPE_LANGS) ) )
55
56 #define C_TID_CHECK_LEGAL(TID,TINFO) C_TYPE_CHECK( \
57 c_tid_check_legal( (TID), (TINFO), ARRAY_SIZE(TINFO) ) )
58
59 #define C_TID_NAME_CAT(SBUF,TIDS,TIDS_SET,IN_ENGLISH,SEP,PSEP) \
60 c_tid_name_cat( (SBUF), (TIDS), (TIDS_SET), ARRAY_SIZE(TIDS_SET), \
61 (IN_ENGLISH), (SEP), (PSEP) )
62
63 /// @endcond
64
65 c_type_t const T_NONE = { TB_NONE, TS_NONE, TA_NONE };
66 c_type_t const T_ANY = { TB_ANY, TS_ANY, TA_ANY };
67 c_type_t const T_ANY_CONST_CLASS = { TB_ANY_CLASS, TS_CONST, TA_NONE };
68 c_type_t const T_TS_TYPEDEF = { TB_NONE, TS_TYPEDEF, TA_NONE };
69
70 ///////////////////////////////////////////////////////////////////////////////
71
72 /**
73 * Mapping between C type bits, valid language(s), and literals.
74 */
75 struct c_type_info {
76 c_tid_t tid; ///< The type.
77 c_lang_id_t lang_ids; ///< Language(s) OK in.
78 char const *english_lit; ///< English version (if not NULL).
79
80 /**
81 * Array of language(s)/literal pair(s). The array is terminated by an
82 * element that has #LANG_ANY for lang_ids; hence subset(s) of language(s)
83 * cases come first and, failing to match opt_lang against any of those,
84 * matches the last (default) element.
85 */
86 c_lang_lit_t const *lang_lit;
87 };
88 typedef struct c_type_info c_type_info_t;
89
90 // local functions
91 PJL_WARN_UNUSED_RESULT
92 static char const* c_type_literal( c_type_info_t const*, bool );
93
94 ///////////////////////////////////////////////////////////////////////////////
95
96 /**
97 * As part of the special case for `long long`, its literal is only `long`
98 * because its type, #TB_LONG_LONG, is always combined with #TB_LONG, i.e., two
99 * bits are set. Therefore, when printed, it prints one `long` for #TB_LONG
100 * and another `long` for #TB_LONG_LONG (this literal). That explains why this
101 * literal is only one `long`.
102 */
103 static char const L_LONG_LONG[] = "long";
104
105 /**
106 * For convenience, this is just a concatenation of `L_RVALUE` and
107 * `L_REFERENCE`.
108 */
109 static char const L_RVALUE_REFERENCE[] = "rvalue reference";
110
111 /**
112 * #TB_TYPEDEF exists only so there can be a row/column for it in the \ref
113 * OK_TYPE_LANGS table to make things like `signed size_t` illegal.
114 *
115 * #TB_TYPEDEF doesn't have any printable representation (only the name of the
116 * type is printed); therefore, its literal is the empty string.
117 */
118 static char const L_TYPEDEF_TYPE[] = "";
119
120 /**
121 * Type mapping for attributes.
122 */
123 static c_type_info_t const C_ATTRIBUTE_INFO[] = {
124 { TA_CARRIES_DEPENDENCY, LANG_CPP_MIN(11), "carries dependency",
125 C_LANG_LIT( { LANG_ANY, L_CARRIES_DEPENDENCY } ) },
126
127 { TA_DEPRECATED, LANG_C_CPP_MIN(2X,11), NULL,
128 C_LANG_LIT( { LANG_ANY, L_DEPRECATED } ) },
129
130 { TA_MAYBE_UNUSED, LANG_C_CPP_MIN(2X,17), "maybe unused",
131 C_LANG_LIT( { LANG_ANY, L_MAYBE_UNUSED } ) },
132
133 { TA_NODISCARD, LANG_C_CPP_MIN(2X,17), H_NON_DISCARDABLE,
134 C_LANG_LIT( { LANG_ANY, L_NODISCARD } ) },
135
136 { TA_NORETURN, LANG_C_CPP_MIN(11,11), H_NON_RETURNING,
137 C_LANG_LIT( { LANG_C_ANY, L__NORETURN },
138 { LANG_ANY, L_NORETURN } ) },
139
140 { TA_NO_UNIQUE_ADDRESS, LANG_CPP_MIN(20), H_NON_UNIQUE_ADDRESS,
141 C_LANG_LIT( { LANG_ANY, L_NO_UNIQUE_ADDRESS } ) },
142
143 // Microsoft extensions
144 { TA_MSC_CDECL, LANG_MIN(C_89), L_MSC_CDECL,
145 C_LANG_LIT( { LANG_ANY, L_MSC___CDECL } ) },
146
147 { TA_MSC_CLRCALL, LANG_MIN(C_89), L_MSC_CLRCALL,
148 C_LANG_LIT( { LANG_ANY, L_MSC___CLRCALL } ) },
149
150 { TA_MSC_FASTCALL, LANG_MIN(C_89), L_MSC_FASTCALL,
151 C_LANG_LIT( { LANG_ANY, L_MSC___FASTCALL } ) },
152
153 { TA_MSC_STDCALL, LANG_MIN(C_89), L_MSC_STDCALL,
154 C_LANG_LIT( { LANG_ANY, L_MSC___STDCALL } ) },
155
156 { TA_MSC_THISCALL, LANG_MIN(C_89), L_MSC_THISCALL,
157 C_LANG_LIT( { LANG_ANY, L_MSC___THISCALL } ) },
158
159 { TA_MSC_VECTORCALL, LANG_MIN(C_89), L_MSC_VECTORCALL,
160 C_LANG_LIT( { LANG_ANY, L_MSC___VECTORCALL } ) },
161 };
162
163 /**
164 * Type mapping for qualifiers.
165 *
166 * @note
167 * This array _must_ have the same size and order as OK_QUALIFIER_LANGS.
168 */
169 static c_type_info_t const C_QUALIFIER_INFO[] = {
170 { TS_ATOMIC, LANG_C_CPP_MIN(11,23), L_ATOMIC,
171 C_LANG_LIT( { LANG_ANY, L__ATOMIC } ) },
172
173 { TS_CONST, LANG_ANY, L_CONSTANT,
174 C_LANG_LIT( { LANG_C_KNR, L_GNU___CONST },
175 { LANG_ANY, L_CONST } ) },
176
177 { TS_REFERENCE, LANG_CPP_MIN(11), NULL,
178 C_LANG_LIT( { LANG_ANY, L_REFERENCE } ) },
179
180 { TS_RVALUE_REFERENCE, LANG_CPP_MIN(11), NULL,
181 C_LANG_LIT( { LANG_ANY, L_RVALUE_REFERENCE } ) },
182
183 { TS_RESTRICT, LANG_ANY, L_RESTRICTED,
184 C_LANG_LIT( { LANG_C_MAX(95) | LANG_CPP_ANY, L_GNU___RESTRICT },
185 { LANG_ANY, L_RESTRICT } ) },
186
187 { TS_VOLATILE, LANG_ANY, NULL,
188 C_LANG_LIT( { LANG_C_KNR, L_GNU___VOLATILE },
189 { LANG_ANY, L_VOLATILE } ) },
190
191 // Unified Parallel C extensions
192 { TS_UPC_RELAXED, LANG_C_99, NULL,
193 C_LANG_LIT( { LANG_ANY, L_UPC_RELAXED } ) },
194
195 { TS_UPC_SHARED, LANG_C_99, NULL,
196 C_LANG_LIT( { LANG_ANY, L_UPC_SHARED } ) },
197
198 { TS_UPC_STRICT, LANG_C_99, NULL,
199 C_LANG_LIT( { LANG_ANY, L_UPC_STRICT } ) },
200 };
201
202 /**
203 * Type mapping for storage classes (or storage-class-like).
204 *
205 * @note
206 * This array _must_ have the same size and order as OK_STORAGE_LANGS.
207 */
208 static c_type_info_t const C_STORAGE_INFO[] = {
209 // storage classes
210 { TS_AUTO, LANG_MAX(CPP_03), L_AUTOMATIC,
211 C_LANG_LIT( { LANG_ANY, L_AUTO } ) },
212
213 { TS_APPLE_BLOCK, LANG_ANY, NULL,
214 C_LANG_LIT( { LANG_ANY, L_APPLE___BLOCK } ) },
215
216 { TS_EXTERN, LANG_ANY, L_EXTERNAL,
217 C_LANG_LIT( { LANG_ANY, L_EXTERN } ) },
218
219 { TS_EXTERN_C, LANG_CPP_ANY, "external \"C\" linkage",
220 C_LANG_LIT( { LANG_ANY, "extern \"C\"" } ) },
221
222 { TS_REGISTER, LANG_MAX(CPP_14), NULL,
223 C_LANG_LIT( { LANG_ANY, L_REGISTER } ) },
224
225 { TS_STATIC, LANG_ANY, NULL,
226 C_LANG_LIT( { LANG_ANY, L_STATIC } ) },
227
228 { TS_THREAD_LOCAL, LANG_ANY, "thread local",
229 C_LANG_LIT( { LANG_C_MAX(99) | LANG_CPP_MAX(03), L_GNU___THREAD },
230 { LANG_C_MIN(11), L__THREAD_LOCAL },
231 { LANG_ANY, L_THREAD_LOCAL } ) },
232
233 { TS_TYPEDEF, LANG_ANY, L_TYPE,
234 C_LANG_LIT( { LANG_ANY, L_TYPEDEF } ) },
235
236 // storage-class-like
237 { TS_CONSTEVAL, LANG_CPP_MIN(20), "constant evaluation",
238 C_LANG_LIT( { LANG_ANY, L_CONSTEVAL } ) },
239
240 { TS_CONSTEXPR, LANG_CPP_MIN(11), "constant expression",
241 C_LANG_LIT( { LANG_ANY, L_CONSTEXPR } ) },
242
243 { TS_CONSTINIT, LANG_CPP_MIN(20), "constant initialization",
244 C_LANG_LIT( { LANG_ANY, L_CONSTINIT } ) },
245
246 { TS_DEFAULT, LANG_CPP_MIN(11), NULL,
247 C_LANG_LIT( { LANG_ANY, L_DEFAULT } ) },
248
249 { TS_DELETE, LANG_CPP_MIN(11), L_DELETED,
250 C_LANG_LIT( { LANG_ANY, L_DELETE } ) },
251
252 { TS_EXPLICIT, LANG_CPP_ANY, NULL,
253 C_LANG_LIT( { LANG_ANY, L_EXPLICIT } ) },
254
255 { TS_EXPORT, LANG_CPP_MIN(20), L_EXPORTED,
256 C_LANG_LIT( { LANG_ANY, L_EXPORT } ) },
257
258 { TS_FINAL, LANG_CPP_MIN(11), NULL,
259 C_LANG_LIT( { LANG_ANY, L_FINAL } ) },
260
261 { TS_FRIEND, LANG_CPP_ANY, NULL,
262 C_LANG_LIT( { LANG_ANY, L_FRIEND } ) },
263
264 { TS_INLINE, LANG_ANY, NULL,
265 C_LANG_LIT( { LANG_C_KNR, L_GNU___INLINE },
266 { LANG_ANY, L_INLINE } ) },
267
268 { TS_MUTABLE, LANG_CPP_ANY, NULL,
269 C_LANG_LIT( { LANG_ANY, L_MUTABLE } ) },
270
271 { TS_NOEXCEPT, LANG_CPP_MIN(11), H_NO_EXCEPTION,
272 C_LANG_LIT( { LANG_ANY, L_NOEXCEPT } ) },
273
274 { TS_OVERRIDE, LANG_CPP_MIN(11), L_OVERRIDDEN,
275 C_LANG_LIT( { LANG_ANY, L_OVERRIDE } ) },
276
277 { TS_THROW, LANG_CPP_ANY, H_NON_THROWING,
278 C_LANG_LIT( { LANG_ANY, L_THROW } ) },
279
280 { TS_VIRTUAL, LANG_CPP_ANY, NULL,
281 C_LANG_LIT( { LANG_ANY, L_VIRTUAL } ) },
282
283 { TS_PURE_VIRTUAL, LANG_CPP_ANY, NULL,
284 C_LANG_LIT( { LANG_ANY, L_PURE } ) },
285 };
286
287 /**
288 * Type mapping for simpler types.
289 *
290 * @note
291 * This array _must_ have the same size and order as OK_TYPE_LANGS.
292 */
293 static c_type_info_t const C_TYPE_INFO[] = {
294 { TB_VOID, LANG_MIN(C_89), NULL,
295 C_LANG_LIT( { LANG_ANY, L_VOID } ) },
296
297 { TB_AUTO, LANG_MIN(C_89), L_AUTOMATIC,
298 C_LANG_LIT( { LANG_MAX(CPP_03), L_GNU___AUTO_TYPE },
299 { LANG_ANY, L_AUTO } ) },
300
301 { TB_BOOL, LANG_MIN(C_99), NULL,
302 C_LANG_LIT( { LANG_C_ANY, L__BOOL },
303 { LANG_ANY, L_BOOL } ) },
304
305 { TB_CHAR, LANG_ANY, NULL,
306 C_LANG_LIT( { LANG_ANY, L_CHAR } ) },
307
308 { TB_CHAR8_T, LANG_C_CPP_MIN(2X,20), NULL,
309 C_LANG_LIT( { LANG_ANY, L_CHAR8_T } ) },
310
311 { TB_CHAR16_T, LANG_C_CPP_MIN(11,11), NULL,
312 C_LANG_LIT( { LANG_ANY, L_CHAR16_T } ) },
313
314 { TB_CHAR32_T, LANG_C_CPP_MIN(11,11), NULL,
315 C_LANG_LIT( { LANG_ANY, L_CHAR32_T } ) },
316
317 { TB_WCHAR_T, LANG_MIN(C_95), NULL,
318 C_LANG_LIT( { LANG_ANY, L_WCHAR_T } ) },
319
320 { TB_SHORT, LANG_ANY, NULL,
321 C_LANG_LIT( { LANG_ANY, L_SHORT } ) },
322
323 { TB_INT, LANG_ANY, NULL,
324 C_LANG_LIT( { LANG_ANY, L_INT } ) },
325
326 { TB_LONG, LANG_ANY, NULL,
327 C_LANG_LIT( { LANG_ANY, L_LONG } ) },
328
329 { TB_LONG_LONG, LANG_MIN(C_99), NULL,
330 C_LANG_LIT( { LANG_ANY, L_LONG_LONG } ) },
331
332 { TB_SIGNED, LANG_ANY, NULL,
333 C_LANG_LIT( { LANG_C_KNR, L_GNU___SIGNED },
334 { LANG_ANY, L_SIGNED } ) },
335
336 { TB_UNSIGNED, LANG_ANY, NULL,
337 C_LANG_LIT( { LANG_ANY, L_UNSIGNED } ) },
338
339 { TB_FLOAT, LANG_ANY, NULL,
340 C_LANG_LIT( { LANG_ANY, L_FLOAT } ) },
341
342 { TB_DOUBLE, LANG_ANY, NULL,
343 C_LANG_LIT( { LANG_ANY, L_DOUBLE } ) },
344
345 { TB_COMPLEX, LANG_C_ANY, L_COMPLEX,
346 C_LANG_LIT( { LANG_C_MAX(95), L_GNU___COMPLEX },
347 { LANG_ANY, L__COMPLEX } ) },
348
349 { TB_IMAGINARY, LANG_C_MIN(99), L_IMAGINARY,
350 C_LANG_LIT( { LANG_ANY, L__IMAGINARY } ) },
351
352 { TB_ENUM, LANG_MIN(C_89), L_ENUMERATION,
353 C_LANG_LIT( { LANG_ANY, L_ENUM } ) },
354
355 { TB_STRUCT, LANG_ANY, L_STRUCTURE,
356 C_LANG_LIT( { LANG_ANY, L_STRUCT } ) },
357
358 { TB_UNION, LANG_ANY, NULL,
359 C_LANG_LIT( { LANG_ANY, L_UNION } ) },
360
361 { TB_CLASS, LANG_CPP_ANY, NULL,
362 C_LANG_LIT( { LANG_ANY, L_CLASS } ) },
363
364 { TB_TYPEDEF, LANG_ANY, NULL,
365 C_LANG_LIT( { LANG_ANY, L_TYPEDEF_TYPE } ) },
366
367 // Embedded C extensions
368 { TB_EMC_ACCUM, LANG_C_99, L_EMC_ACCUM,
369 C_LANG_LIT( { LANG_ANY, L_EMC__ACCUM } ) },
370
371 { TB_EMC_FRACT, LANG_C_99, L_EMC_FRACT,
372 C_LANG_LIT( { LANG_ANY, L_EMC__FRACT } ) },
373
374 { TB_EMC_SAT, LANG_C_99, L_EMC_SATURATED,
375 C_LANG_LIT( { LANG_ANY, L_EMC__SAT } ) },
376 };
377
378 /// @cond DOXYGEN_IGNORE
379
380 // shorthand legal in ...
381 #define __ LANG_ANY
382 #define XX LANG_NONE
383 #define KR LANG_C_KNR
384 #define C8 LANG_MIN(C_89)
385 #define C5 LANG_MIN(C_95)
386 #define c9 LANG_C_99
387 #define C9 LANG_MIN(C_99)
388 #define C1 LANG_MIN(C_11)
389 #define PP LANG_CPP_ANY
390 #define P3 LANG_CPP_MIN(03)
391 #define P1 LANG_CPP_MIN(11)
392 #define P2 LANG_CPP_MIN(20)
393 #define E1 LANG_C_CPP_MIN(11,11)
394 #define E2 LANG_C_CPP_MIN(2X,20)
395 #define E3 LANG_C_CPP_MIN(11,23)
396
397 /// @endcond
398
399 // There is no OK_ATTRIBUTE_LANGS because all combinations of attributes are
400 // legal.
401
402 /**
403 * Legal combinations of qualifiers in languages.
404 *
405 * @note
406 * This array _must_ have the same size and order as C_QUALIFIER_INFO.
407 */
408 static c_lang_id_t const OK_QUALIFIER_LANGS[][ ARRAY_SIZE( C_QUALIFIER_INFO ) ] = {
409 // Only the lower triangle is used.
410 // a c r rr re v rx sh st
411 { E3,__,__,__,__,__, __,__,__ }, // atomic
412 { E1,__,__,__,__,__, __,__,__ }, // const
413 { XX,PP,PP,__,__,__, __,__,__ }, // reference
414 { XX,P1,XX,P1,__,__, __,__,__ }, // rvalue reference
415 { XX,__,PP,P1,__,__, __,__,__ }, // restrict
416 { E1,__,PP,P1,__,__, __,__,__ }, // volatile
417
418 // Unified Parallel C extensions
419 { XX,c9,XX,XX,c9,c9, c9,__,__ }, // relaxed
420 { XX,c9,XX,XX,c9,c9, c9,c9,__ }, // shared
421 { XX,c9,XX,XX,c9,c9, XX,c9,c9 }, // strict
422 };
423
424 /**
425 * Legal combinations of storage classes in languages.
426 *
427 * @note
428 * This array _must_ have the same size and order as C_STORAGE_INFO.
429 */
430 static c_lang_id_t const OK_STORAGE_LANGS[][ ARRAY_SIZE( C_STORAGE_INFO ) ] = {
431 // Only the lower triangle is used.
432 // a b e ec,r s th td cv cx ci df de ex ep fi fr in mu ne o t v pv
433 { __,__,__,__,__,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// auto
434 { __,__,__,__,__,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// block
435 { XX,__,__,__,__,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// extern
436 { XX,__,__,PP,__,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// extern C
437 { XX,__,XX,XX,__,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// register
438 { XX,XX,XX,XX,XX,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// static
439 { XX,__,__,P1,XX,__,__,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// thread
440 { XX,__,XX,PP,XX,XX,XX,__, __,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// typedef
441
442 { P1,P1,P1,P2,XX,P1,XX,XX, P2,P1,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// c'eval
443 { P1,P1,P1,P1,XX,P1,XX,XX, XX,P1,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// c'expr
444 { XX,XX,P2,P2,XX,P2,P2,XX, XX,XX,P2,__,__,__,__,__,__,__,__,__,__,__,__,__ },// c'init
445 { XX,XX,XX,XX,XX,XX,XX,XX, P1,P1,XX,P1,__,__,__,__,__,__,__,__,__,__,__,__ },// default
446 { XX,XX,XX,XX,XX,XX,XX,XX, P1,P1,XX,XX,P1,__,__,__,__,__,__,__,__,__,__,__ },// delete
447 { XX,XX,XX,XX,XX,XX,XX,XX, XX,P1,XX,P1,P1,PP,__,__,__,__,__,__,__,__,__,__ },// explicit
448 { XX,XX,P2,XX,XX,XX,XX,XX, XX,P2,P2,XX,XX,XX,P2,__,__,__,__,__,__,__,__,__ },// export
449 { XX,XX,XX,XX,XX,XX,XX,XX, XX,P1,XX,XX,XX,XX,XX,P1,__,__,__,__,__,__,__,__ },// final
450 { XX,XX,XX,XX,XX,XX,XX,XX, P2,P1,XX,P2,XX,XX,XX,XX,PP,__,__,__,__,__,__,__ },// friend
451 { XX,XX,__,PP,XX,__,XX,XX, P2,P1,P2,P1,P1,PP,P2,P1,PP,C9,__,__,__,__,__,__ },// inline
452 { XX,XX,XX,XX,XX,XX,XX,XX, XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,P3,__,__,__,__,__ },// mutable
453 { XX,XX,P1,PP,XX,P1,XX,P1, P2,P1,XX,P1,P1,PP,P2,P1,P1,P1,XX,P1,__,__,__,__ },// noexcept
454 { XX,XX,XX,XX,XX,XX,XX,XX, XX,P1,XX,XX,XX,XX,XX,P1,XX,C1,XX,C1,P1,__,__,__ },// override
455 { XX,XX,PP,PP,XX,PP,XX,PP, P2,P1,XX,P1,P1,PP,XX,PP,XX,PP,XX,XX,PP,PP,__,__ },// throw
456 { XX,XX,XX,XX,XX,XX,XX,XX, XX,P2,XX,XX,XX,XX,XX,P1,XX,PP,XX,C1,P1,PP,PP,__ },// virtual
457 { XX,XX,XX,XX,XX,XX,XX,XX, XX,P2,XX,XX,XX,XX,XX,XX,XX,PP,XX,C1,P1,PP,PP,PP },// pure
458 };
459
460 /**
461 * Legal combinations of types in languages.
462 *
463 * @note
464 * This array _must_ have the same size and order as C_TYPE_INFO.
465 */
466 static c_lang_id_t const OK_TYPE_LANGS[][ ARRAY_SIZE( C_TYPE_INFO ) ] = {
467 // Only the lower triangle is used.
468 // v a1 b c 8 16 32 wc s i l ll s u f d co im e st un cl t ac fr sa
469 { C8,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// void
470 { XX,C8,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// auto
471 { XX,XX,C9,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// bool
472 { XX,XX,XX,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// char
473 { XX,XX,XX,XX,E2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// char8_t
474 { XX,XX,XX,XX,XX,E1,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// char16_t
475 { XX,XX,XX,XX,XX,XX,E1,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// char32_t
476 { XX,XX,XX,XX,XX,XX,XX,C5,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// wchar_t
477 { XX,XX,XX,XX,XX,XX,XX,XX,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// short
478 { XX,XX,XX,XX,XX,XX,XX,XX,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// int
479 { XX,XX,XX,XX,XX,XX,XX,XX,XX,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// long
480 { XX,XX,XX,XX,XX,XX,XX,XX,XX,C9,__,C9,__,__,__,__,__,__,__,__,__,__,__,__,__,__ },// long long
481 { XX,XX,XX,C8,XX,XX,XX,XX,C8,C8,C8,C8,C8,__,__,__,__,__,__,__,__,__,__,__,__,__ },// signed
482 { XX,XX,XX,__,XX,XX,XX,XX,__,__,__,C8,XX,__,__,__,__,__,__,__,__,__,__,__,__,__ },// unsigned
483 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,KR,XX,XX,XX,__,__,__,__,__,__,__,__,__,__,__,__ },// float
484 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,C8,XX,XX,XX,XX,__,__,__,__,__,__,__,__,__,__,__ },// double
485 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,C9,C9,C9,__,__,__,__,__,__,__,__,__ },// complex
486 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,C9,C9,XX,C9,__,__,__,__,__,__,__,__ },// imaginary
487 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,C8,__,__,__,__,__,__,__ },// enum
488 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,P1,__,__,__,__,__,__,__ },// struct
489 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,__,__,__,__,__,__ },// union
490 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,P1,XX,XX,PP,__,__,__,__ },// class
491 { XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,__,__,__,__ },// typedef
492 { XX,XX,XX,XX,XX,XX,XX,XX,C9,XX,C9,XX,C9,C9,XX,XX,XX,XX,XX,XX,XX,XX,XX,C9,__,__ },// _Accum
493 { XX,XX,XX,XX,XX,XX,XX,XX,C9,XX,C9,XX,C9,C9,XX,XX,XX,XX,XX,XX,XX,XX,XX,XX,C9,__ },// _Fract
494 { XX,XX,XX,XX,XX,XX,XX,XX,C9,XX,C9,XX,C9,C9,XX,XX,XX,XX,XX,XX,XX,XX,XX,C9,C9,C9 },// _Sat
495 };
496
497 ////////// inline functions ///////////////////////////////////////////////////
498
499 /**
500 * Checks whether \a tids is some form of `long int` only, and _not_ one of
501 * `long float` (K&R), `long double` (C89), or either `long _Accum` or `long
502 * _Fract` (Embedded C).
503 *
504 * @param tids The \ref c_tid_t to check.
505 * @return Returns `true` only if \a tids is some form of `long int`.
506 */
507 PJL_WARN_UNUSED_RESULT
c_tid_is_long_int(c_tid_t tids)508 static inline bool c_tid_is_long_int( c_tid_t tids ) {
509 return c_tid_tpid( tids ) == C_TPID_BASE &&
510 c_tid_is_except( tids, TB_LONG, TB_ANY_FLOAT | TB_ANY_EMC );
511 }
512
513 ////////// local functions ////////////////////////////////////////////////////
514
515 /**
516 * Checks that the type combination is legal in the current language.
517 *
518 * @param tids The \ref c_tid_t to check.
519 * @param type_infos The array of \ref c_type_info to check against.
520 * @param type_infos_size The size of \a type_infos.
521 * @param type_langs The type/languages array to check against.
522 * @return Returns the bitwise-or of the language(s) \a tids is legal in.
523 */
524 PJL_WARN_UNUSED_RESULT
525 static c_lang_id_t
c_tid_check_combo(c_tid_t tids,c_type_info_t const type_infos[],size_t type_infos_size,c_lang_id_t const type_langs[][type_infos_size])526 c_tid_check_combo( c_tid_t tids, c_type_info_t const type_infos[],
527 size_t type_infos_size,
528 c_lang_id_t const type_langs[][type_infos_size] ) {
529 for ( size_t row = 0; row < type_infos_size; ++row ) {
530 if ( !c_tid_is_none( tids & type_infos[ row ].tid ) ) {
531 for ( size_t col = 0; col <= row; ++col ) {
532 c_lang_id_t const lang_ids = type_langs[ row ][ col ];
533 if ( !c_tid_is_none( tids & type_infos[ col ].tid ) &&
534 !opt_lang_is_any( lang_ids ) ) {
535 return lang_ids;
536 }
537 } // for
538 }
539 } // for
540 return LANG_ANY;
541 }
542
543 /**
544 * Checks that \a tids is legal in the current language.
545 *
546 * @param tids The \ref c_tid_t to check.
547 * @param type_infos The array of \ref c_type_info to check against.
548 * @param type_infos_size The size of \a type_infos.
549 * @return Returns the bitwise-or of the language(s) \a tids is legal in.
550 */
551 PJL_WARN_UNUSED_RESULT
552 static c_lang_id_t
c_tid_check_legal(c_tid_t tids,c_type_info_t const type_infos[],size_t type_infos_size)553 c_tid_check_legal( c_tid_t tids, c_type_info_t const type_infos[],
554 size_t type_infos_size ) {
555 for ( size_t row = 0; row < type_infos_size; ++row ) {
556 c_type_info_t const *const ti = &type_infos[ row ];
557 if ( !c_tid_is_none( tids & ti->tid ) && !opt_lang_is_any( ti->lang_ids ) )
558 return ti->lang_ids;
559 } // for
560 return LANG_ANY;
561 }
562
563 /**
564 * Gets the name of an individual type.
565 *
566 * @param tid The \ref c_tid_t to get the name for; \a tid _must_ have _exactly
567 * one_ bit set.
568 * @param in_english If `true`, return the pseudo-English literal if one
569 * exists.
570 * @return Returns said name.
571 */
572 PJL_WARN_UNUSED_RESULT
c_tid_name_1(c_tid_t tid,bool in_english)573 static char const* c_tid_name_1( c_tid_t tid, bool in_english ) {
574 assert( exactly_one_bit_set( c_tid_no_tpid( tid ) ) );
575
576 switch ( c_tid_tpid( tid ) ) {
577 case C_TPID_NONE:
578 break; // LCOV_EXCL_LINE
579
580 case C_TPID_BASE:
581 for ( size_t i = 0; i < ARRAY_SIZE( C_TYPE_INFO ); ++i ) {
582 c_type_info_t const *const ti = &C_TYPE_INFO[i];
583 if ( tid == ti->tid )
584 return c_type_literal( ti, in_english );
585 } // for
586 break; // LCOV_EXCL_LINE
587
588 case C_TPID_STORE:
589 for ( size_t i = 0; i < ARRAY_SIZE( C_QUALIFIER_INFO ); ++i ) {
590 c_type_info_t const *const ti = &C_QUALIFIER_INFO[i];
591 if ( tid == ti->tid )
592 return c_type_literal( ti, in_english );
593 } // for
594
595 for ( size_t i = 0; i < ARRAY_SIZE( C_STORAGE_INFO ); ++i ) {
596 c_type_info_t const *const ti = &C_STORAGE_INFO[i];
597 if ( tid == ti->tid )
598 return c_type_literal( ti, in_english );
599 } // for
600 break; // LCOV_EXCL_LINE
601
602 case C_TPID_ATTR:
603 for ( size_t i = 0; i < ARRAY_SIZE( C_ATTRIBUTE_INFO ); ++i ) {
604 c_type_info_t const *const ti = &C_ATTRIBUTE_INFO[i];
605 if ( tid == ti->tid )
606 return c_type_literal( ti, in_english );
607 } // for
608 break; // LCOV_EXCL_LINE
609 } // switch
610
611 UNEXPECTED_INT_VALUE( tid );
612 }
613
614 /**
615 * Concatenates the partial type name onto the full type name being made.
616 *
617 * @param sbuf A pointer to the buffer to concatenate the name to.
618 * @param tids The \ref c_tid_t to concatenate the name of.
619 * @param tids_set The array of types to use.
620 * @param tids_set_size The size of \a tids_set.
621 * @param in_english If `true`, return the pseudo-English literal if one
622 * exists.
623 * @param sep The separator character.
624 * @param sep_flag A pointer to a variable to keep track of whether \a sep has
625 * been concatenated.
626 */
c_tid_name_cat(strbuf_t * sbuf,c_tid_t tids,c_tid_t const tids_set[],size_t tids_set_size,bool in_english,char sep,bool * sep_flag)627 static void c_tid_name_cat( strbuf_t *sbuf, c_tid_t tids,
628 c_tid_t const tids_set[], size_t tids_set_size,
629 bool in_english, char sep, bool *sep_flag ) {
630 for ( size_t i = 0; i < tids_set_size; ++i ) {
631 if ( !c_tid_is_none( tids & tids_set[i] ) ) {
632 char const *const name = c_tid_name_1( tids_set[i], in_english );
633 strbuf_sepc_puts( sbuf, sep, sep_flag, name );
634 }
635 } // for
636 }
637
638 /**
639 * "Simplifies" a base \ref c_tid_t. Specifically:
640 *
641 * + If \a btids is #TB_SIGNED and not #TB_CHAR, remove #TB_SIGNED.
642 * + If \a btids becomes #TB_NONE, make it #TB_INT.
643 *
644 * @param btids The \ref c_tid_t to simplify.
645 * @return Returns the simplified \ref c_tid_t.
646 */
647 PJL_WARN_UNUSED_RESULT
c_tid_simplify(c_tid_t btids)648 static c_tid_t c_tid_simplify( c_tid_t btids ) {
649 assert( c_tid_tpid( btids ) == C_TPID_BASE );
650 if ( c_tid_is_except( btids, TB_SIGNED, TB_CHAR ) ) {
651 btids &= c_tid_compl( TB_SIGNED );
652 if ( btids == TB_NONE )
653 btids = TB_INT;
654 }
655 return btids;
656 }
657
658 /**
659 * Gets the literal of a given \ref c_type_info, either gibberish or, if
660 * appropriate and available, pseudo-English.
661 *
662 * @param ti The \ref c_type_info to get the literal of.
663 * @param in_english If `true`, return the pseudo-English literal if one
664 * exists.
665 * @return Returns said literal.
666 */
667 PJL_WARN_UNUSED_RESULT
c_type_literal(c_type_info_t const * ti,bool in_english)668 static char const* c_type_literal( c_type_info_t const *ti, bool in_english ) {
669 return in_english && ti->english_lit != NULL ?
670 ti->english_lit : c_lang_literal( ti->lang_lit );
671 }
672
673 /**
674 * Gets the name of \a type.
675 *
676 * @param type The type to get the name for.
677 * @param apply_explicit_ecsu If `true`, apply \ref opt_explicit_ecsu.
678 * @param in_english If `true`, return the pseudo-English name if possible.
679 * @param is_error If `true`, the name is intended for use in an error message.
680 * Specifically, c_tid_normalize() is _not_ called.
681 * @return Returns said name.
682 *
683 * @warning The pointer returned is to a small number of static buffers, so you
684 * can't do something like call this more than twice in the same `printf()`
685 * statement.
686 *
687 * @sa c_tid_normalize()
688 * @sa c_type_name_c()
689 * @sa c_type_name_ecsu()
690 * @sa c_type_name_english()
691 * @sa c_type_name_error()
692 */
693 PJL_WARN_UNUSED_RESULT
c_type_name_impl(c_type_t const * type,bool apply_explicit_ecsu,bool in_english,bool is_error)694 static char const* c_type_name_impl( c_type_t const *type,
695 bool apply_explicit_ecsu, bool in_english,
696 bool is_error ) {
697 static strbuf_t sbufs[ 2 ];
698 static unsigned buf_index;
699
700 strbuf_t *const sbuf = &sbufs[ buf_index++ % ARRAY_SIZE( sbufs ) ];
701 strbuf_reset( sbuf );
702 bool space = false;
703
704 c_tid_t btids = is_error ? type->btids : c_tid_simplify( type->btids );
705 c_tid_t stids = type->stids;
706 c_tid_t atids = type->atids;
707
708 if ( OPT_LANG_IS(C_ANY) && c_tid_is_any( atids, TA_NORETURN ) ) {
709 //
710 // Special case: we store _Noreturn as an attribute, but in C, it's a
711 // distinct keyword and printed as such instead being printed between
712 // brackets [[like this]].
713 //
714 static c_tid_t const ATIDS[] = { TA_NORETURN };
715 C_TID_NAME_CAT( sbuf, TA_NORETURN, ATIDS, in_english, ' ', &space );
716 //
717 // Now that we've handled _Noreturn for C, remove its bit and fall through
718 // to the regular attribute-printing code.
719 //
720 atids &= c_tid_compl( TA_NORETURN );
721 }
722
723 if ( c_tid_is_any( atids, c_tid_compl( TA_ANY_MSC_CALL ) ) ) {
724 static c_tid_t const ATIDS[] = {
725 TA_CARRIES_DEPENDENCY,
726 TA_DEPRECATED,
727 TA_MAYBE_UNUSED,
728 TA_NODISCARD,
729 TA_NORETURN, // still here for C++'s [[noreturn]]
730 TA_NO_UNIQUE_ADDRESS,
731 };
732 // Microsoft calling conventions must be handled later -- see below.
733
734 bool const print_brackets =
735 OPT_LANG_IS(MIN(C_2X)) &&
736 cdecl_mode == CDECL_ENGLISH_TO_GIBBERISH && !in_english;
737
738 bool comma = false;
739 char const sep = print_brackets ? ',' : ' ';
740 bool *const sep_cat = print_brackets ? &comma : &space;
741
742 if ( print_brackets )
743 strbuf_sepc_puts( sbuf, ' ', &space, graph_token_c( "[[" ) );
744 C_TID_NAME_CAT( sbuf, atids, ATIDS, in_english, sep, sep_cat );
745 if ( print_brackets )
746 strbuf_puts( sbuf, graph_token_c( "]]" ) );
747 space = true;
748 }
749
750 // Special cases.
751 if ( in_english ) {
752 if ( c_tid_is_any( btids, TB_ANY_MODIFIER ) &&
753 !c_tid_is_any( btids, c_tid_compl( TB_ANY_MODIFIER ) ) ) {
754 // In English, be explicit about "int".
755 btids |= TB_INT;
756 }
757 if ( c_tid_is_any( stids, TS_FINAL | TS_OVERRIDE ) ) {
758 // In English, either "final" or "overrride" implies "virtual".
759 stids |= TS_VIRTUAL;
760 }
761 }
762 else /* !in_english */ {
763 //
764 // In C++, at most one of "virtual", "override", or "final" should be
765 // printed. The type is massaged in g_print_ast() since "virtual" prints
766 // before the function signature and either "override" or "final" prints
767 // after. Hence, by the time we get here, at most one bit should be set.
768 //
769 assert(
770 at_most_one_bit_set(
771 c_tid_no_tpid( stids & (TS_VIRTUAL | TS_OVERRIDE | TS_FINAL) )
772 )
773 );
774
775 if ( is_explicit_int( btids ) ) {
776 btids |= TB_INT;
777 } else if ( c_tid_is_any( btids, TB_ANY_MODIFIER ) ) {
778 // In C/C++, explicit "int" isn't needed when at least one int modifier
779 // is present.
780 btids &= c_tid_compl( TB_INT );
781 }
782 }
783
784 // Types here MUST have a corresponding row AND column in OK_STORAGE_LANGS.
785 static c_tid_t const STIDS[] = {
786
787 // These are first so we get names like "deleted constructor".
788 TS_DEFAULT,
789 TS_DELETE,
790 TS_EXTERN_C,
791
792 // This is next so "typedef" comes before (almost) everything else.
793 TS_TYPEDEF,
794
795 // These are next so we get names like "static int".
796 TS_AUTO,
797 TS_APPLE_BLOCK,
798 TS_EXPORT,
799 TS_EXTERN,
800 TS_FRIEND,
801 TS_REGISTER,
802 TS_MUTABLE,
803 TS_STATIC,
804 TS_THREAD_LOCAL,
805
806 // These are next so we get names like "static inline".
807 TS_EXPLICIT,
808 TS_INLINE,
809
810 // These are next so we get names like "static inline final".
811 TS_OVERRIDE,
812 TS_FINAL,
813
814 // These are next so we get names like "overridden virtual".
815 TS_PURE_VIRTUAL,
816 TS_VIRTUAL,
817 TS_NOEXCEPT,
818 TS_THROW,
819
820 // These are next so we get names like "static inline constexpr".
821 TS_CONSTEVAL,
822 TS_CONSTEXPR,
823 TS_CONSTINIT,
824 };
825 C_TID_NAME_CAT( sbuf, stids, STIDS, in_english, ' ', &space );
826
827 c_tid_t east_stids = TS_NONE;
828 if ( opt_east_const && !in_english ) {
829 east_stids = stids & TS_CV;
830 stids &= c_tid_compl( TS_CV );
831 }
832
833 static c_tid_t const QUAL_STIDS[] = {
834 // These are before "shared" so we get names like "strict shared".
835 TS_UPC_RELAXED,
836 TS_UPC_STRICT,
837
838 TS_UPC_SHARED,
839
840 TS_CONST,
841 TS_RESTRICT,
842 TS_VOLATILE,
843
844 // These are next so we get names like "const reference".
845 TS_REFERENCE,
846 TS_RVALUE_REFERENCE,
847
848 // This is last so we get names like "const _Atomic".
849 TS_ATOMIC,
850 };
851 C_TID_NAME_CAT( sbuf, stids, QUAL_STIDS, in_english, ' ', &space );
852
853 if ( OPT_LANG_IS(CPP_ANY) && apply_explicit_ecsu &&
854 !in_english && !is_error && c_tid_is_any( btids, TB_ANY_CLASS ) ) {
855 btids &= opt_explicit_ecsu;
856 }
857
858 //
859 // Special case: C++23 adds an _Atomic(T) macro for compatibility with C11,
860 // but while _Atomic can be printed without () in C, they're required in C++:
861 //
862 // _Atomic int x; // C11 only
863 // _Atomic(int) y; // C11 or C++23
864 //
865 // Note that this handles printing () only for non-typedef types; for typedef
866 // types, see the similar special case for K_TYPEDEF in g_ast_print().
867 //
868 bool const print_parens_for_cpp23_Atomic =
869 OPT_LANG_IS(CPP_MIN(23)) && !in_english &&
870 c_tid_is_any( stids, TS_ATOMIC ) && !c_tid_is_any( btids, TB_TYPEDEF );
871
872 if ( print_parens_for_cpp23_Atomic ) {
873 strbuf_putc( sbuf, '(' );
874 space = false;
875 }
876
877 static c_tid_t const BTIDS[] = {
878 // These are first so we get names like "unsigned int".
879 TB_SIGNED,
880 TB_UNSIGNED,
881
882 // These are next so we get names like "unsigned long int".
883 TB_SHORT,
884 TB_LONG,
885 TB_LONG_LONG,
886
887 TB_VOID,
888 TB_AUTO,
889 TB_BOOL,
890 TB_CHAR,
891 TB_CHAR8_T,
892 TB_CHAR16_T,
893 TB_CHAR32_T,
894 TB_WCHAR_T,
895 TB_INT,
896 TB_COMPLEX,
897 TB_IMAGINARY,
898 TB_FLOAT,
899 TB_DOUBLE,
900 TB_ENUM,
901 TB_STRUCT,
902 TB_UNION,
903 TB_CLASS,
904
905 // This is next so we get names like "unsigned long _Sat _Fract".
906 TB_EMC_SAT,
907
908 TB_EMC_ACCUM,
909 TB_EMC_FRACT,
910 };
911 C_TID_NAME_CAT( sbuf, btids, BTIDS, in_english, ' ', &space );
912
913 if ( print_parens_for_cpp23_Atomic )
914 strbuf_putc( sbuf, ')' );
915
916 // Microsoft calling conventions must be handled here.
917 static c_tid_t const MSC_CALL_ATIDS[] = {
918 TA_MSC_CDECL,
919 TA_MSC_CLRCALL,
920 TA_MSC_FASTCALL,
921 TA_MSC_STDCALL,
922 TA_MSC_THISCALL,
923 TA_MSC_VECTORCALL,
924 };
925 C_TID_NAME_CAT( sbuf, atids, MSC_CALL_ATIDS, in_english, ' ', &space );
926
927 if ( east_stids != TS_NONE )
928 C_TID_NAME_CAT( sbuf, east_stids, QUAL_STIDS, in_english, ' ', &space );
929
930 // Really special cases.
931 if ( c_tid_is_any( btids, TB_NAMESPACE ) )
932 strbuf_sepc_puts( sbuf, ' ', &space, L_NAMESPACE );
933 else if ( c_tid_is_any( btids, TB_SCOPE ) )
934 strbuf_sepc_puts( sbuf, ' ', &space, L_SCOPE );
935
936 return sbuf->str != NULL ? sbuf->str : "";
937 }
938
939 ////////// extern functions ///////////////////////////////////////////////////
940
c_type_add(c_type_t * dst_type,c_type_t const * new_type,c_loc_t const * new_loc)941 bool c_type_add( c_type_t *dst_type, c_type_t const *new_type,
942 c_loc_t const *new_loc ) {
943 assert( dst_type != NULL );
944 assert( new_type != NULL );
945
946 return c_tid_add( &dst_type->btids, new_type->btids, new_loc ) &&
947 c_tid_add( &dst_type->stids, new_type->stids, new_loc ) &&
948 c_tid_add( &dst_type->atids, new_type->atids, new_loc );
949 }
950
c_type_add_tid(c_type_t * dst_type,c_tid_t new_tids,c_loc_t const * new_loc)951 bool c_type_add_tid( c_type_t *dst_type, c_tid_t new_tids,
952 c_loc_t const *new_loc ) {
953 c_tid_t *const dst_tids = c_type_get_tid_ptr( dst_type, new_tids );
954 return c_tid_add( dst_tids, new_tids, new_loc );
955 }
956
c_type_and(c_type_t const * i_type,c_type_t const * j_type)957 c_type_t c_type_and( c_type_t const *i_type, c_type_t const *j_type ) {
958 assert( i_type != NULL );
959 assert( j_type != NULL );
960
961 return C_TYPE_LIT(
962 i_type->btids & j_type->btids,
963 i_type->stids & j_type->stids,
964 i_type->atids & j_type->atids
965 );
966 }
967
c_type_and_eq_compl(c_type_t * dst_type,c_type_t const * rm_type)968 void c_type_and_eq_compl( c_type_t *dst_type, c_type_t const *rm_type ) {
969 assert( dst_type != NULL );
970 assert( rm_type != NULL );
971
972 dst_type->btids &= c_tid_compl( rm_type->btids );
973 dst_type->stids &= c_tid_compl( rm_type->stids );
974 dst_type->atids &= c_tid_compl( rm_type->atids );
975 }
976
c_type_check(c_type_t const * type)977 c_lang_id_t c_type_check( c_type_t const *type ) {
978 // Check that the attribute(s) are legal in the current language.
979 C_TID_CHECK_LEGAL( type->atids, C_ATTRIBUTE_INFO );
980
981 // Check that the storage class is legal in the current language.
982 C_TID_CHECK_LEGAL( type->stids, C_STORAGE_INFO );
983
984 // Check that the type is legal in the current language.
985 C_TID_CHECK_LEGAL( type->btids, C_TYPE_INFO );
986
987 // Check that the qualifier(s) are legal in the current language.
988 C_TID_CHECK_LEGAL( type->stids, C_QUALIFIER_INFO );
989
990 // Check that the storage class combination is legal in the current language.
991 C_TID_CHECK_COMBO( type->stids, C_STORAGE_INFO, OK_STORAGE_LANGS );
992
993 // Check that the type combination is legal in the current language.
994 C_TID_CHECK_COMBO( type->btids, C_TYPE_INFO, OK_TYPE_LANGS );
995
996 // Check that the qualifier combination is legal in the current language.
997 C_TID_CHECK_COMBO( type->stids, C_QUALIFIER_INFO, OK_QUALIFIER_LANGS );
998
999 return LANG_ANY;
1000 }
1001
c_type_equal(c_type_t const * i_type,c_type_t const * j_type)1002 bool c_type_equal( c_type_t const *i_type, c_type_t const *j_type ) {
1003 assert( i_type != NULL );
1004 assert( j_type != NULL );
1005
1006 if ( i_type->stids != j_type->stids || i_type->atids != j_type->atids )
1007 return false;
1008 c_tid_t const i_btids = c_tid_normalize( i_type->btids );
1009 c_tid_t const j_btids = c_tid_normalize( j_type->btids );
1010 return i_btids == j_btids;
1011 }
1012
c_type_from_tid(c_tid_t tids)1013 c_type_t c_type_from_tid( c_tid_t tids ) {
1014 switch ( c_tid_tpid( tids ) ) {
1015 case C_TPID_NONE:
1016 break; // LCOV_EXCL_LINE
1017 case C_TPID_BASE:
1018 return C_TYPE_LIT_B( tids );
1019 case C_TPID_STORE:
1020 return C_TYPE_LIT_S( tids );
1021 case C_TPID_ATTR:
1022 return C_TYPE_LIT_A( tids );
1023 } // switch
1024
1025 UNEXPECTED_INT_VALUE( tids );
1026 }
1027
c_type_get_tid(c_type_t const * type,c_tid_t tids)1028 c_tid_t c_type_get_tid( c_type_t const *type, c_tid_t tids ) {
1029 assert( type != NULL );
1030
1031 switch ( c_tid_tpid( tids ) ) {
1032 case C_TPID_NONE:
1033 break; // LCOV_EXCL_LINE
1034 case C_TPID_BASE:
1035 return type->btids;
1036 case C_TPID_STORE:
1037 return type->stids;
1038 case C_TPID_ATTR:
1039 return type->atids;
1040 } // switch
1041
1042 UNEXPECTED_INT_VALUE( tids );
1043 }
1044
c_type_get_tid_ptr(c_type_t * type,c_tid_t tids)1045 c_tid_t* c_type_get_tid_ptr( c_type_t *type, c_tid_t tids ) {
1046 assert( type != NULL );
1047
1048 switch ( c_tid_tpid( tids ) ) {
1049 case C_TPID_NONE:
1050 break; // LCOV_EXCL_LINE
1051 case C_TPID_BASE:
1052 return &type->btids;
1053 case C_TPID_STORE:
1054 return &type->stids;
1055 case C_TPID_ATTR:
1056 return &type->atids;
1057 } // switch
1058
1059 UNEXPECTED_INT_VALUE( tids );
1060 }
1061
c_tid_add(c_tid_t * dst_tids,c_tid_t new_tids,c_loc_t const * new_loc)1062 bool c_tid_add( c_tid_t *dst_tids, c_tid_t new_tids, c_loc_t const *new_loc ) {
1063 assert( dst_tids != NULL );
1064 assert( new_loc != NULL );
1065 assert( c_tid_tpid( *dst_tids ) == c_tid_tpid( new_tids ) );
1066
1067 if ( c_tid_is_long_int( *dst_tids ) && c_tid_is_long_int( new_tids ) ) {
1068 //
1069 // Special case: if the existing type is "long" and the new type is "long",
1070 // turn the new type into "long long".
1071 //
1072 new_tids = TB_LONG_LONG;
1073 }
1074
1075 if ( !c_tid_is_none( *dst_tids & new_tids ) ) {
1076 print_error( new_loc,
1077 "\"%s\" can not be combined with \"%s\"\n",
1078 c_tid_name_error( new_tids ), c_tid_name_error( *dst_tids )
1079 );
1080 return false;
1081 }
1082
1083 *dst_tids |= new_tids;
1084 return true;
1085 }
1086
c_tid_name_c(c_tid_t tids)1087 char const* c_tid_name_c( c_tid_t tids ) {
1088 c_type_t const type = c_type_from_tid( tids );
1089 return c_type_name_impl( &type,
1090 /*apply_explicit_ecsu=*/false,
1091 /*in_english=*/false,
1092 /*is_error=*/false
1093 );
1094 }
1095
c_tid_name_english(c_tid_t tids)1096 char const* c_tid_name_english( c_tid_t tids ) {
1097 c_type_t const type = c_type_from_tid( tids );
1098 return c_type_name_impl( &type,
1099 /*apply_explicit_ecsu=*/false,
1100 /*in_english=*/true,
1101 /*is_error=*/false
1102 );
1103 }
1104
1105
c_tid_name_error(c_tid_t tids)1106 char const* c_tid_name_error( c_tid_t tids ) {
1107 c_type_t const type = c_type_from_tid( tids );
1108 // When giving an error message, return the type name in pseudo-English if
1109 // we're parsing pseudo-English or in C/C++ if we're parsing C/C++.
1110 return c_type_name_impl( &type,
1111 /*apply_explicit_ecsu=*/false,
1112 /*in_english=*/cdecl_mode == CDECL_ENGLISH_TO_GIBBERISH,
1113 /*is_error=*/true
1114 );
1115 }
1116
c_tid_normalize(c_tid_t tids)1117 c_tid_t c_tid_normalize( c_tid_t tids ) {
1118 switch ( c_tid_tpid( tids ) ) {
1119 case C_TPID_BASE:
1120 tids = c_tid_simplify( tids );
1121 // If the type is only implicitly int, make it explicitly int.
1122 if ( c_tid_is_except( tids, TB_SHORT, TB_ANY_EMC ) ||
1123 c_tid_is_except( tids, TB_LONG, TB_ANY_FLOAT | TB_ANY_EMC ) ||
1124 c_tid_is_except( tids, TB_UNSIGNED, TB_CHAR | TB_ANY_EMC ) ) {
1125 tids |= TB_INT;
1126 }
1127 break;
1128 default:
1129 /* suppress warning */;
1130 } // switch
1131 return tids;
1132 }
1133
c_tid_scope_order(c_tid_t btids)1134 unsigned c_tid_scope_order( c_tid_t btids ) {
1135 assert( (btids & TX_MASK_TPID) == C_TPID_BASE );
1136 switch ( btids & (TB_ANY_SCOPE | TB_ENUM) ) {
1137 case TB_NONE:
1138 case TB_SCOPE:
1139 return 0;
1140 case TB_NAMESPACE:
1141 return 1;
1142 case TB_STRUCT:
1143 case TB_UNION:
1144 case TB_CLASS:
1145 return 2;
1146 case TB_ENUM:
1147 case TB_ENUM | TB_CLASS:
1148 return 3;
1149 } // switch
1150
1151 UNEXPECTED_INT_VALUE( btids );
1152 }
1153
c_tid_tpid(c_tid_t tids)1154 c_tpid_t c_tid_tpid( c_tid_t tids ) {
1155 //
1156 // If tids has been complemented, e.g., ~TS_REGISTER to denote "all but
1157 // register," then we have to complement tids back first.
1158 //
1159 if ( c_tid_is_compl( tids ) )
1160 tids = ~tids;
1161 tids &= TX_MASK_TPID;
1162 assert( tids <= C_TPID_ATTR );
1163 return STATIC_CAST( c_tpid_t, tids );
1164 }
1165
c_type_is_any(c_type_t const * i_type,c_type_t const * j_type)1166 bool c_type_is_any( c_type_t const *i_type, c_type_t const *j_type ) {
1167 assert( i_type != NULL );
1168 assert( j_type != NULL );
1169
1170 if ( (j_type->stids != TS_NONE &&
1171 (i_type->stids & j_type->stids) == TS_NONE) ||
1172 (j_type->atids != TA_NONE &&
1173 (i_type->atids & j_type->atids) == TA_NONE) ) {
1174 return false;
1175 }
1176
1177 if ( j_type->btids == TB_NONE )
1178 return true;
1179 c_tid_t const i_btids = c_tid_normalize( i_type->btids );
1180 c_tid_t const j_btids = c_tid_normalize( j_type->btids );
1181 return (i_btids & j_btids) != TB_NONE;
1182 }
1183
c_type_name_c(c_type_t const * type)1184 char const* c_type_name_c( c_type_t const *type ) {
1185 return c_type_name_impl( type,
1186 /*apply_explicit_ecsu=*/false,
1187 /*in_english=*/false,
1188 /*is_error=*/false
1189 );
1190 }
1191
c_type_name_ecsu(c_type_t const * type)1192 char const* c_type_name_ecsu( c_type_t const *type ) {
1193 return c_type_name_impl( type,
1194 /*apply_explicit_ecsu=*/true,
1195 /*in_english=*/false,
1196 /*is_error=*/false
1197 );
1198 }
1199
c_type_name_english(c_type_t const * type)1200 char const* c_type_name_english( c_type_t const *type ) {
1201 return c_type_name_impl( type,
1202 /*apply_explicit_ecsu=*/false,
1203 /*in_english=*/true,
1204 /*is_error=*/false
1205 );
1206 }
1207
c_type_name_error(c_type_t const * type)1208 char const* c_type_name_error( c_type_t const *type ) {
1209 // See comment in c_tid_name_error().
1210 return c_type_name_impl(
1211 type,
1212 /*apply_explicit_ecsu=*/false,
1213 /*in_english=*/cdecl_mode == CDECL_ENGLISH_TO_GIBBERISH,
1214 /*is_error=*/true
1215 );
1216 }
1217
c_type_or(c_type_t const * i_type,c_type_t const * j_type)1218 c_type_t c_type_or( c_type_t const *i_type, c_type_t const *j_type ) {
1219 assert( i_type != NULL );
1220 assert( j_type != NULL );
1221
1222 return C_TYPE_LIT(
1223 i_type->btids | j_type->btids,
1224 i_type->stids | j_type->stids,
1225 i_type->atids | j_type->atids
1226 );
1227 }
1228
c_type_or_eq(c_type_t * dst_type,c_type_t const * add_type)1229 void c_type_or_eq( c_type_t *dst_type, c_type_t const *add_type ) {
1230 assert( dst_type != NULL );
1231 assert( add_type != NULL );
1232
1233 dst_type->btids |= add_type->btids;
1234 dst_type->stids |= add_type->stids;
1235 dst_type->atids |= add_type->atids;
1236 }
1237
1238 ///////////////////////////////////////////////////////////////////////////////
1239 /* vim:set et sw=2 ts=2: */
1240