authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-21 14:38:32+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-29 11:04:45+02:00
logfceda07f94c9e4181f97ecacc1bdc1b9a0b7ab16
tree44c4ff6b7f727e430cefaa4ee2af67953c2a332b
parentbda355d976c11a6bf1c820b6f1c2a477acd214fd
signature Commit is signed but in an unrecognized format.

use self hosted translate-c for cimports


11 files changed, 146 insertions(+), 7343 deletions(-)

CMakeLists.txt-2
......@@ -448,7 +448,6 @@ set(ZIG_SOURCES
448448 "${CMAKE_SOURCE_DIR}/src/bigfloat.cpp"
449449 "${CMAKE_SOURCE_DIR}/src/bigint.cpp"
450450 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
451 "${CMAKE_SOURCE_DIR}/src/c_tokenizer.cpp"
452451 "${CMAKE_SOURCE_DIR}/src/cache_hash.cpp"
453452 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
454453 "${CMAKE_SOURCE_DIR}/src/compiler.cpp"
......@@ -465,7 +464,6 @@ set(ZIG_SOURCES
465464 "${CMAKE_SOURCE_DIR}/src/range_set.cpp"
466465 "${CMAKE_SOURCE_DIR}/src/target.cpp"
467466 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
468 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
469467 "${CMAKE_SOURCE_DIR}/src/util.cpp"
470468 "${ZIG_SOURCES_MEM_PROFILE}"
471469)
src/c_tokenizer.cpp deleted-840
......@@ -1,840 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "c_tokenizer.hpp"
9#include <inttypes.h>
10
11#define WHITESPACE_EXCEPT_N \
12 ' ': \
13 case '\t': \
14 case '\v': \
15 case '\f'
16
17#define DIGIT_NON_ZERO \
18 '1': \
19 case '2': \
20 case '3': \
21 case '4': \
22 case '5': \
23 case '6': \
24 case '7': \
25 case '8': \
26 case '9'
27
28#define DIGIT \
29 '0': \
30 case DIGIT_NON_ZERO
31
32#define ALPHA \
33 'a': \
34 case 'b': \
35 case 'c': \
36 case 'd': \
37 case 'e': \
38 case 'f': \
39 case 'g': \
40 case 'h': \
41 case 'i': \
42 case 'j': \
43 case 'k': \
44 case 'l': \
45 case 'm': \
46 case 'n': \
47 case 'o': \
48 case 'p': \
49 case 'q': \
50 case 'r': \
51 case 's': \
52 case 't': \
53 case 'u': \
54 case 'v': \
55 case 'w': \
56 case 'x': \
57 case 'y': \
58 case 'z': \
59 case 'A': \
60 case 'B': \
61 case 'C': \
62 case 'D': \
63 case 'E': \
64 case 'F': \
65 case 'G': \
66 case 'H': \
67 case 'I': \
68 case 'J': \
69 case 'K': \
70 case 'L': \
71 case 'M': \
72 case 'N': \
73 case 'O': \
74 case 'P': \
75 case 'Q': \
76 case 'R': \
77 case 'S': \
78 case 'T': \
79 case 'U': \
80 case 'V': \
81 case 'W': \
82 case 'X': \
83 case 'Y': \
84 case 'Z'
85
86#define IDENT_START \
87 ALPHA: \
88 case '_'
89
90#define IDENT \
91 IDENT_START: \
92 case DIGIT
93
94#define LINE_ENDING \
95 '\r': \
96 case '\n'
97
98static void begin_token(CTokenize *ctok, CTokId id) {
99 assert(ctok->cur_tok == nullptr);
100 ctok->tokens.add_one();
101 ctok->cur_tok = &ctok->tokens.last();
102 ctok->cur_tok->id = id;
103
104 switch (id) {
105 case CTokIdStrLit:
106 memset(&ctok->cur_tok->data.str_lit, 0, sizeof(Buf));
107 buf_resize(&ctok->cur_tok->data.str_lit, 0);
108 break;
109 case CTokIdSymbol:
110 memset(&ctok->cur_tok->data.symbol, 0, sizeof(Buf));
111 buf_resize(&ctok->cur_tok->data.symbol, 0);
112 break;
113 case CTokIdNumLitInt:
114 ctok->cur_tok->data.num_lit_int.x = 0;
115 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixNone;
116 break;
117 case CTokIdCharLit:
118 case CTokIdNumLitFloat:
119 case CTokIdMinus:
120 case CTokIdLParen:
121 case CTokIdRParen:
122 case CTokIdEOF:
123 case CTokIdDot:
124 case CTokIdAsterisk:
125 case CTokIdBang:
126 case CTokIdTilde:
127 case CTokIdShl:
128 case CTokIdLt:
129 break;
130 }
131}
132
133static void end_token(CTokenize *ctok) {
134 ctok->cur_tok = nullptr;
135}
136
137static void mark_error(CTokenize *ctok) {
138 ctok->error = true;
139}
140
141static void add_char(CTokenize *ctok, uint8_t c) {
142 assert(ctok->cur_tok);
143 if (ctok->cur_tok->id == CTokIdCharLit) {
144 ctok->cur_tok->data.char_lit = c;
145 ctok->state = CTokStateExpectEndQuot;
146 } else if (ctok->cur_tok->id == CTokIdStrLit) {
147 buf_append_char(&ctok->cur_tok->data.str_lit, c);
148 ctok->state = CTokStateString;
149 } else {
150 zig_unreachable();
151 }
152}
153
154static void hex_digit(CTokenize *ctok, uint8_t value) {
155 // TODO @mul_with_overflow
156 ctok->cur_tok->data.num_lit_int.x *= 16;
157 // TODO @add_with_overflow
158 ctok->cur_tok->data.num_lit_int.x += value;
159
160 static const uint8_t hex_digit[] = "0123456789abcdef";
161 buf_append_char(&ctok->buf, hex_digit[value]);
162}
163
164static void end_float(CTokenize *ctok) {
165 // TODO detect errors, overflow, and underflow
166 double value = strtod(buf_ptr(&ctok->buf), nullptr);
167
168 ctok->cur_tok->data.num_lit_float = value;
169
170 end_token(ctok);
171 ctok->state = CTokStateStart;
172
173}
174
175void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
176 ctok->tokens.resize(0);
177 ctok->state = CTokStateStart;
178 ctok->error = false;
179 ctok->cur_tok = nullptr;
180
181 buf_resize(&ctok->buf, 0);
182
183 for (; *c; c += 1) {
184 switch (ctok->state) {
185 case CTokStateStart:
186 switch (*c) {
187 case WHITESPACE_EXCEPT_N:
188 break;
189 case '\'':
190 ctok->state = CTokStateExpectChar;
191 begin_token(ctok, CTokIdCharLit);
192 break;
193 case '\"':
194 ctok->state = CTokStateString;
195 begin_token(ctok, CTokIdStrLit);
196 break;
197 case '/':
198 ctok->state = CTokStateOpenComment;
199 break;
200 case '\\':
201 ctok->state = CTokStateBackslash;
202 break;
203 case LINE_ENDING:
204 goto found_end_of_macro;
205 case IDENT_START:
206 ctok->state = CTokStateIdentifier;
207 begin_token(ctok, CTokIdSymbol);
208 buf_append_char(&ctok->cur_tok->data.symbol, *c);
209 break;
210 case DIGIT_NON_ZERO:
211 ctok->state = CTokStateDecimal;
212 begin_token(ctok, CTokIdNumLitInt);
213 ctok->cur_tok->data.num_lit_int.x = *c - '0';
214 buf_resize(&ctok->buf, 0);
215 buf_append_char(&ctok->buf, *c);
216 break;
217 case '0':
218 ctok->state = CTokStateGotZero;
219 begin_token(ctok, CTokIdNumLitInt);
220 ctok->cur_tok->data.num_lit_int.x = 0;
221 buf_resize(&ctok->buf, 0);
222 buf_append_char(&ctok->buf, '0');
223 break;
224 case '.':
225 begin_token(ctok, CTokIdDot);
226 end_token(ctok);
227 break;
228 case '<':
229 begin_token(ctok, CTokIdLt);
230 ctok->state = CTokStateGotLt;
231 break;
232 case '(':
233 begin_token(ctok, CTokIdLParen);
234 end_token(ctok);
235 break;
236 case ')':
237 begin_token(ctok, CTokIdRParen);
238 end_token(ctok);
239 break;
240 case '*':
241 begin_token(ctok, CTokIdAsterisk);
242 end_token(ctok);
243 break;
244 case '-':
245 begin_token(ctok, CTokIdMinus);
246 end_token(ctok);
247 break;
248 case '!':
249 begin_token(ctok, CTokIdBang);
250 end_token(ctok);
251 break;
252 case '~':
253 begin_token(ctok, CTokIdTilde);
254 end_token(ctok);
255 break;
256 default:
257 return mark_error(ctok);
258 }
259 break;
260 case CTokStateGotLt:
261 switch (*c) {
262 case '<':
263 ctok->cur_tok->id = CTokIdShl;
264 end_token(ctok);
265 ctok->state = CTokStateStart;
266 break;
267 default:
268 end_token(ctok);
269 ctok->state = CTokStateStart;
270 continue;
271 }
272 break;
273 case CTokStateFloat:
274 switch (*c) {
275 case '.':
276 break;
277 case 'e':
278 case 'E':
279 buf_append_char(&ctok->buf, 'e');
280 ctok->state = CTokStateExpSign;
281 break;
282 case 'f':
283 case 'F':
284 case 'l':
285 case 'L':
286 end_float(ctok);
287 break;
288 case DIGIT:
289 buf_append_char(&ctok->buf, *c);
290 break;
291 default:
292 c -= 1;
293 end_float(ctok);
294 continue;
295 }
296 break;
297 case CTokStateExpSign:
298 switch (*c) {
299 case '+':
300 case '-':
301 ctok->state = CTokStateFloatExpFirst;
302 buf_append_char(&ctok->buf, *c);
303 break;
304 case DIGIT:
305 ctok->state = CTokStateFloatExp;
306 buf_append_char(&ctok->buf, *c);
307 break;
308 default:
309 return mark_error(ctok);
310 }
311 break;
312 case CTokStateFloatExpFirst:
313 switch (*c) {
314 case DIGIT:
315 buf_append_char(&ctok->buf, *c);
316 ctok->state = CTokStateFloatExp;
317 break;
318 default:
319 return mark_error(ctok);
320 }
321 break;
322 case CTokStateFloatExp:
323 switch (*c) {
324 case DIGIT:
325 buf_append_char(&ctok->buf, *c);
326 break;
327 case 'f':
328 case 'F':
329 case 'l':
330 case 'L':
331 end_float(ctok);
332 break;
333 default:
334 c -= 1;
335 end_float(ctok);
336 continue;
337 }
338 break;
339 case CTokStateDecimal:
340 switch (*c) {
341 case DIGIT:
342 buf_append_char(&ctok->buf, *c);
343
344 // TODO @mul_with_overflow
345 ctok->cur_tok->data.num_lit_int.x *= 10;
346 // TODO @add_with_overflow
347 ctok->cur_tok->data.num_lit_int.x += *c - '0';
348 break;
349 case '\'':
350 break;
351 case 'u':
352 case 'U':
353 ctok->state = CTokStateNumLitIntSuffixU;
354 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixU;
355 break;
356 case 'l':
357 case 'L':
358 ctok->state = CTokStateNumLitIntSuffixL;
359 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixL;
360 break;
361 case '.':
362 buf_append_char(&ctok->buf, '.');
363 ctok->cur_tok->id = CTokIdNumLitFloat;
364 ctok->state = CTokStateFloat;
365 break;
366 default:
367 c -= 1;
368 end_token(ctok);
369 ctok->state = CTokStateStart;
370 continue;
371 }
372 break;
373 case CTokStateGotZero:
374 switch (*c) {
375 case 'x':
376 case 'X':
377 ctok->state = CTokStateHex;
378 break;
379 case '.':
380 ctok->state = CTokStateFloat;
381 ctok->cur_tok->id = CTokIdNumLitFloat;
382 buf_append_char(&ctok->buf, '.');
383 break;
384 case 'l':
385 case 'L':
386 case 'u':
387 case 'U':
388 c -= 1;
389 ctok->state = CTokStateDecimal;
390 continue;
391 default:
392 c -= 1;
393 ctok->state = CTokStateOctal;
394 continue;
395 }
396 break;
397 case CTokStateOctal:
398 switch (*c) {
399 case '0':
400 case '1':
401 case '2':
402 case '3':
403 case '4':
404 case '5':
405 case '6':
406 case '7':
407 // TODO @mul_with_overflow
408 ctok->cur_tok->data.num_lit_int.x *= 8;
409 // TODO @add_with_overflow
410 ctok->cur_tok->data.num_lit_int.x += *c - '0';
411 break;
412 case '8':
413 case '9':
414 return mark_error(ctok);
415 case '\'':
416 break;
417 default:
418 c -= 1;
419 end_token(ctok);
420 ctok->state = CTokStateStart;
421 continue;
422 }
423 break;
424 case CTokStateHex:
425 switch (*c) {
426 case '0':
427 hex_digit(ctok, 0);
428 break;
429 case '1':
430 hex_digit(ctok, 1);
431 break;
432 case '2':
433 hex_digit(ctok, 2);
434 break;
435 case '3':
436 hex_digit(ctok, 3);
437 break;
438 case '4':
439 hex_digit(ctok, 4);
440 break;
441 case '5':
442 hex_digit(ctok, 5);
443 break;
444 case '6':
445 hex_digit(ctok, 6);
446 break;
447 case '7':
448 hex_digit(ctok, 7);
449 break;
450 case '8':
451 hex_digit(ctok, 8);
452 break;
453 case '9':
454 hex_digit(ctok, 9);
455 break;
456 case 'a':
457 case 'A':
458 hex_digit(ctok, 10);
459 break;
460 case 'b':
461 case 'B':
462 hex_digit(ctok, 11);
463 break;
464 case 'c':
465 case 'C':
466 hex_digit(ctok, 12);
467 break;
468 case 'd':
469 case 'D':
470 hex_digit(ctok, 13);
471 break;
472 case 'e':
473 case 'E':
474 hex_digit(ctok, 14);
475 break;
476 case 'f':
477 case 'F':
478 hex_digit(ctok, 15);
479 break;
480 case 'p':
481 case 'P':
482 ctok->cur_tok->id = CTokIdNumLitFloat;
483 ctok->state = CTokStateExpSign;
484 break;
485 case 'u':
486 case 'U':
487 // marks the number literal as unsigned
488 ctok->state = CTokStateNumLitIntSuffixU;
489 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixU;
490 break;
491 case 'l':
492 case 'L':
493 // marks the number literal as long
494 ctok->state = CTokStateNumLitIntSuffixL;
495 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixL;
496 break;
497 default:
498 c -= 1;
499 end_token(ctok);
500 ctok->state = CTokStateStart;
501 continue;
502 }
503 break;
504 case CTokStateNumLitIntSuffixU:
505 switch (*c) {
506 case 'l':
507 case 'L':
508 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLU;
509 ctok->state = CTokStateNumLitIntSuffixUL;
510 break;
511 default:
512 c -= 1;
513 end_token(ctok);
514 ctok->state = CTokStateStart;
515 continue;
516 }
517 break;
518 case CTokStateNumLitIntSuffixL:
519 switch (*c) {
520 case 'l':
521 case 'L':
522 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLL;
523 ctok->state = CTokStateNumLitIntSuffixLL;
524 break;
525 case 'u':
526 case 'U':
527 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLU;
528 end_token(ctok);
529 ctok->state = CTokStateStart;
530 break;
531 default:
532 c -= 1;
533 end_token(ctok);
534 ctok->state = CTokStateStart;
535 continue;
536 }
537 break;
538 case CTokStateNumLitIntSuffixLL:
539 switch (*c) {
540 case 'u':
541 case 'U':
542 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLLU;
543 end_token(ctok);
544 ctok->state = CTokStateStart;
545 break;
546 default:
547 c -= 1;
548 end_token(ctok);
549 ctok->state = CTokStateStart;
550 continue;
551 }
552 break;
553 case CTokStateNumLitIntSuffixUL:
554 switch (*c) {
555 case 'l':
556 case 'L':
557 ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLLU;
558 end_token(ctok);
559 ctok->state = CTokStateStart;
560 break;
561 default:
562 c -= 1;
563 end_token(ctok);
564 ctok->state = CTokStateStart;
565 continue;
566 }
567 break;
568 case CTokStateIdentifier:
569 switch (*c) {
570 case IDENT:
571 buf_append_char(&ctok->cur_tok->data.symbol, *c);
572 break;
573 default:
574 c -= 1;
575 end_token(ctok);
576 ctok->state = CTokStateStart;
577 continue;
578 }
579 break;
580 case CTokStateString:
581 switch (*c) {
582 case '\\':
583 ctok->state = CTokStateCharEscape;
584 break;
585 case '\"':
586 end_token(ctok);
587 ctok->state = CTokStateStart;
588 break;
589 default:
590 buf_append_char(&ctok->cur_tok->data.str_lit, *c);
591 }
592 break;
593 case CTokStateExpectChar:
594 switch (*c) {
595 case '\\':
596 ctok->state = CTokStateCharEscape;
597 break;
598 case '\'':
599 return mark_error(ctok);
600 default:
601 ctok->cur_tok->data.char_lit = *c;
602 ctok->state = CTokStateExpectEndQuot;
603 }
604 break;
605 case CTokStateCharEscape:
606 switch (*c) {
607 case '\'':
608 case '"':
609 case '?':
610 case '\\':
611 add_char(ctok, *c);
612 break;
613 case 'a':
614 add_char(ctok, '\a');
615 break;
616 case 'b':
617 add_char(ctok, '\b');
618 break;
619 case 'f':
620 add_char(ctok, '\f');
621 break;
622 case 'n':
623 add_char(ctok, '\n');
624 break;
625 case 'r':
626 add_char(ctok, '\r');
627 break;
628 case 't':
629 add_char(ctok, '\t');
630 break;
631 case 'v':
632 add_char(ctok, '\v');
633 break;
634 case '0':
635 case '1':
636 case '2':
637 case '3':
638 case '4':
639 case '5':
640 case '6':
641 case '7':
642 ctok->state = CTokStateStrOctal;
643 ctok->cur_char = (uint8_t)(*c - '0');
644 ctok->octal_index = 1;
645 break;
646 case 'x':
647 ctok->state = CTokStateStrHex;
648 ctok->cur_char = 0;
649 break;
650 case 'u':
651 zig_panic("TODO unicode");
652 break;
653 case 'U':
654 zig_panic("TODO Unicode");
655 break;
656 default:
657 return mark_error(ctok);
658 }
659 break;
660 case CTokStateStrHex: {
661 uint8_t value = 0;
662 switch (*c) {
663 case '0':
664 case '1':
665 case '2':
666 case '3':
667 case '4':
668 case '5':
669 case '6':
670 case '7':
671 case '8':
672 case '9':
673 value = *c - '0';
674 break;
675 case 'a':
676 case 'b':
677 case 'c':
678 case 'd':
679 case 'e':
680 case 'f':
681 value = (*c - 'a') + 10;
682 break;
683 case 'A':
684 case 'B':
685 case 'C':
686 case 'D':
687 case 'E':
688 case 'F':
689 value = (*c - 'A') + 10;
690 break;
691 default:
692 c -= 1;
693 add_char(ctok, ctok->cur_char);
694 continue;
695 }
696 // TODO @mul_with_overflow
697 if (((long)ctok->cur_char) * 16 >= 256) {
698 zig_panic("TODO str hex mul overflow");
699 }
700 ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)16);
701 // TODO @add_with_overflow
702 if (((long)ctok->cur_char) + (long)(value) >= 256) {
703 zig_panic("TODO str hex add overflow");
704 }
705 ctok->cur_char = (uint8_t)(ctok->cur_char + value);
706 break;
707 }
708 case CTokStateStrOctal:
709 switch (*c) {
710 case '0':
711 case '1':
712 case '2':
713 case '3':
714 case '4':
715 case '5':
716 case '6':
717 case '7':
718 // TODO @mul_with_overflow
719 if (((long)ctok->cur_char) * 8 >= 256) {
720 zig_panic("TODO");
721 }
722 ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)8);
723 // TODO @add_with_overflow
724 if (((long)ctok->cur_char) + (long)(*c - '0') >= 256) {
725 zig_panic("TODO");
726 }
727 ctok->cur_char = (uint8_t)(ctok->cur_char + (uint8_t)(*c - '0'));
728 ctok->octal_index += 1;
729 if (ctok->octal_index == 3) {
730 add_char(ctok, ctok->cur_char);
731 }
732 break;
733 default:
734 c -= 1;
735 add_char(ctok, ctok->cur_char);
736 continue;
737 }
738 break;
739 case CTokStateExpectEndQuot:
740 switch (*c) {
741 case '\'':
742 end_token(ctok);
743 ctok->state = CTokStateStart;
744 break;
745 default:
746 return mark_error(ctok);
747 }
748 break;
749 case CTokStateOpenComment:
750 switch (*c) {
751 case '/':
752 ctok->state = CTokStateLineComment;
753 break;
754 case '*':
755 ctok->state = CTokStateComment;
756 break;
757 default:
758 return mark_error(ctok);
759 }
760 break;
761 case CTokStateLineComment:
762 if (*c == '\n') {
763 ctok->state = CTokStateStart;
764 goto found_end_of_macro;
765 }
766 break;
767 case CTokStateComment:
768 switch (*c) {
769 case '*':
770 ctok->state = CTokStateCommentStar;
771 break;
772 default:
773 break;
774 }
775 break;
776 case CTokStateCommentStar:
777 switch (*c) {
778 case '/':
779 ctok->state = CTokStateStart;
780 break;
781 case '*':
782 break;
783 default:
784 ctok->state = CTokStateComment;
785 break;
786 }
787 break;
788 case CTokStateBackslash:
789 switch (*c) {
790 case '\n':
791 ctok->state = CTokStateStart;
792 break;
793 default:
794 return mark_error(ctok);
795 }
796 break;
797 }
798 }
799found_end_of_macro:
800
801 switch (ctok->state) {
802 case CTokStateStart:
803 break;
804 case CTokStateIdentifier:
805 case CTokStateDecimal:
806 case CTokStateHex:
807 case CTokStateOctal:
808 case CTokStateGotZero:
809 case CTokStateNumLitIntSuffixU:
810 case CTokStateNumLitIntSuffixL:
811 case CTokStateNumLitIntSuffixUL:
812 case CTokStateNumLitIntSuffixLL:
813 case CTokStateGotLt:
814 end_token(ctok);
815 break;
816 case CTokStateFloat:
817 case CTokStateFloatExp:
818 end_float(ctok);
819 break;
820 case CTokStateExpectChar:
821 case CTokStateExpectEndQuot:
822 case CTokStateOpenComment:
823 case CTokStateLineComment:
824 case CTokStateComment:
825 case CTokStateCommentStar:
826 case CTokStateCharEscape:
827 case CTokStateBackslash:
828 case CTokStateString:
829 case CTokStateExpSign:
830 case CTokStateFloatExpFirst:
831 case CTokStateStrHex:
832 case CTokStateStrOctal:
833 return mark_error(ctok);
834 }
835
836 assert(ctok->cur_tok == nullptr);
837
838 begin_token(ctok, CTokIdEOF);
839 end_token(ctok);
840}
src/c_tokenizer.hpp deleted-98
......@@ -1,98 +0,0 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8
9#ifndef ZIG_C_TOKENIZER_HPP
10#define ZIG_C_TOKENIZER_HPP
11
12#include "buffer.hpp"
13
14enum CTokId {
15 CTokIdCharLit,
16 CTokIdStrLit,
17 CTokIdNumLitInt,
18 CTokIdNumLitFloat,
19 CTokIdSymbol,
20 CTokIdMinus,
21 CTokIdLParen,
22 CTokIdRParen,
23 CTokIdEOF,
24 CTokIdDot,
25 CTokIdAsterisk,
26 CTokIdBang,
27 CTokIdTilde,
28 CTokIdShl,
29 CTokIdLt,
30};
31
32enum CNumLitSuffix {
33 CNumLitSuffixNone,
34 CNumLitSuffixL,
35 CNumLitSuffixU,
36 CNumLitSuffixLU,
37 CNumLitSuffixLL,
38 CNumLitSuffixLLU,
39};
40
41struct CNumLitInt {
42 uint64_t x;
43 CNumLitSuffix suffix;
44};
45
46struct CTok {
47 enum CTokId id;
48 union {
49 uint8_t char_lit;
50 Buf str_lit;
51 CNumLitInt num_lit_int;
52 double num_lit_float;
53 Buf symbol;
54 } data;
55};
56
57enum CTokState {
58 CTokStateStart,
59 CTokStateExpectChar,
60 CTokStateCharEscape,
61 CTokStateExpectEndQuot,
62 CTokStateOpenComment,
63 CTokStateLineComment,
64 CTokStateComment,
65 CTokStateCommentStar,
66 CTokStateBackslash,
67 CTokStateString,
68 CTokStateIdentifier,
69 CTokStateDecimal,
70 CTokStateOctal,
71 CTokStateGotZero,
72 CTokStateHex,
73 CTokStateFloat,
74 CTokStateExpSign,
75 CTokStateFloatExp,
76 CTokStateFloatExpFirst,
77 CTokStateStrHex,
78 CTokStateStrOctal,
79 CTokStateNumLitIntSuffixU,
80 CTokStateNumLitIntSuffixL,
81 CTokStateNumLitIntSuffixLL,
82 CTokStateNumLitIntSuffixUL,
83 CTokStateGotLt,
84};
85
86struct CTokenize {
87 ZigList<CTok> tokens;
88 CTokState state;
89 bool error;
90 CTok *cur_tok;
91 Buf buf;
92 uint8_t cur_char;
93 int octal_index;
94};
95
96void tokenize_c_macro(CTokenize *ctok, const uint8_t *c);
97
98#endif
src/codegen.cpp+4-20
......@@ -15,7 +15,6 @@
1515#include "hash_map.hpp"
1616#include "ir.hpp"
1717#include "os.hpp"
18#include "translate_c.hpp"
1918#include "target.hpp"
2019#include "util.hpp"
2120#include "zig_llvm.h"
......@@ -9090,7 +9089,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
90909089
90919090}
90929091
9093void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) {
9092void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file) {
90949093 Error err;
90959094 Buf *src_basename = buf_alloc();
90969095 Buf *src_dirname = buf_alloc();
......@@ -9103,10 +9102,6 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
91039102
91049103 init(g);
91059104
9106 TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
9107 TranslateModeImport : TranslateModeTranslate;
9108
9109
91109105 ZigList<const char *> clang_argv = {0};
91119106 add_cc_args(g, clang_argv, nullptr, true);
91129107
......@@ -9126,15 +9121,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
91269121 Stage2ErrorMsg *errors_ptr;
91279122 size_t errors_len;
91289123 Stage2Ast *ast;
9129 AstNode *root_node;
91309124
9131 if (use_userland_implementation) {
9132 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
9133 &clang_argv.at(0), &clang_argv.last(), resources_path);
9134 } else {
9135 err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
9136 trans_mode, resources_path);
9137 }
9125 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
9126 &clang_argv.at(0), &clang_argv.last(), resources_path);
91389127
91399128 if (err == ErrorCCompileErrors && errors_len > 0) {
91409129 for (size_t i = 0; i < errors_len; i += 1) {
......@@ -9158,12 +9147,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
91589147 exit(1);
91599148 }
91609149
9161
9162 if (use_userland_implementation) {
9163 stage2_render_ast(ast, out_file);
9164 } else {
9165 ast_render(out_file, root_node, 4);
9166 }
9150 stage2_render_ast(ast, out_file);
91679151}
91689152
91699153static void update_test_functions_builtin_decl(CodeGen *g) {
src/codegen.hpp+1-1
......@@ -54,7 +54,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
5454void codegen_add_assembly(CodeGen *g, Buf *path);
5555void codegen_add_object(CodeGen *g, Buf *object_path);
5656
57void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation);
57void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file);
5858
5959Buf *codegen_generate_builtin_source(CodeGen *g);
6060
src/ir.cpp+4-5
......@@ -13,7 +13,6 @@
1313#include "os.hpp"
1414#include "range_set.hpp"
1515#include "softfloat.hpp"
16#include "translate_c.hpp"
1716#include "util.hpp"
1817
1918#include <errno.h>
......@@ -23755,14 +23754,14 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
2375523754
2375623755 clang_argv.append(nullptr); // to make the [start...end] argument work
2375723756
23758 AstNode *root_node;
2375923757 Stage2ErrorMsg *errors_ptr;
2376023758 size_t errors_len;
23759 Stage2Ast *ast;
2376123760
2376223761 const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
2376323762
23764 if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
23765 &clang_argv.at(0), &clang_argv.last(), TranslateModeImport, resources_path)))
23763 if ((err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
23764 &clang_argv.at(0), &clang_argv.last(), resources_path)))
2376623765 {
2376723766 if (err != ErrorCCompileErrors) {
2376823767 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
......@@ -23813,7 +23812,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
2381323812 buf_sprintf("C import failed: unable to open output file: %s", strerror(errno)));
2381423813 return ira->codegen->invalid_instruction;
2381523814 }
23816 ast_render(out_file, root_node, 4);
23815 stage2_render_ast(ast, out_file);
2381723816 if (fclose(out_file) != 0) {
2381823817 ir_add_error_node(ira, node,
2381923818 buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno)));
src/main.cpp+5-11
......@@ -243,7 +243,6 @@ enum Cmd {
243243 CmdTargets,
244244 CmdTest,
245245 CmdTranslateC,
246 CmdTranslateCUserland,
247246 CmdVersion,
248247 CmdZen,
249248 CmdLibC,
......@@ -960,8 +959,6 @@ int main(int argc, char **argv) {
960959 cmd = CmdLibC;
961960 } else if (strcmp(arg, "translate-c") == 0) {
962961 cmd = CmdTranslateC;
963 } else if (strcmp(arg, "translate-c-2") == 0) {
964 cmd = CmdTranslateCUserland;
965962 } else if (strcmp(arg, "test") == 0) {
966963 cmd = CmdTest;
967964 out_type = OutTypeExe;
......@@ -978,7 +975,6 @@ int main(int argc, char **argv) {
978975 case CmdBuild:
979976 case CmdRun:
980977 case CmdTranslateC:
981 case CmdTranslateCUserland:
982978 case CmdTest:
983979 case CmdLibC:
984980 if (!in_file) {
......@@ -1112,7 +1108,6 @@ int main(int argc, char **argv) {
11121108 case CmdRun:
11131109 case CmdBuild:
11141110 case CmdTranslateC:
1115 case CmdTranslateCUserland:
11161111 case CmdTest:
11171112 {
11181113 if (cmd == CmdBuild && !in_file && objects.length == 0 &&
......@@ -1124,7 +1119,7 @@ int main(int argc, char **argv) {
11241119 " * --object argument\n"
11251120 " * --c-source argument\n");
11261121 return print_error_usage(arg0);
1127 } else if ((cmd == CmdTranslateC || cmd == CmdTranslateCUserland ||
1122 } else if ((cmd == CmdTranslateC ||
11281123 cmd == CmdTest || cmd == CmdRun) && !in_file)
11291124 {
11301125 fprintf(stderr, "Expected source file argument.\n");
......@@ -1136,7 +1131,7 @@ int main(int argc, char **argv) {
11361131
11371132 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
11381133
1139 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC || cmd == CmdTranslateCUserland);
1134 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);
11401135
11411136 if (cmd == CmdRun) {
11421137 out_name = "run";
......@@ -1170,8 +1165,7 @@ int main(int argc, char **argv) {
11701165 return print_error_usage(arg0);
11711166 }
11721167
1173 Buf *zig_root_source_file = (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) ?
1174 nullptr : in_file_buf;
1168 Buf *zig_root_source_file = cmd == CmdTranslateC ? nullptr : in_file_buf;
11751169
11761170 if (cmd == CmdRun && buf_out_name == nullptr) {
11771171 buf_out_name = buf_create_from_str("run");
......@@ -1336,8 +1330,8 @@ int main(int argc, char **argv) {
13361330 } else {
13371331 zig_unreachable();
13381332 }
1339 } else if (cmd == CmdTranslateC || cmd == CmdTranslateCUserland) {
1340 codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);
1333 } else if (cmd == CmdTranslateC) {
1334 codegen_translate_c(g, in_file_buf, stdout);
13411335 if (timing_info)
13421336 codegen_print_timing_report(g, stderr);
13431337 return main_exit(root_progress_node, EXIT_SUCCESS);
src/translate_c.cpp deleted-5156
......@@ -1,5156 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7#include "all_types.hpp"
8#include "analyze.hpp"
9#include "c_tokenizer.hpp"
10#include "error.hpp"
11#include "ir.hpp"
12#include "os.hpp"
13#include "translate_c.hpp"
14#include "parser.hpp"
15#include "zig_clang.h"
16
17#include <string.h>
18
19struct Alias {
20 Buf *new_name;
21 Buf *canon_name;
22};
23
24enum TransScopeId {
25 TransScopeIdSwitch,
26 TransScopeIdVar,
27 TransScopeIdBlock,
28 TransScopeIdRoot,
29 TransScopeIdWhile,
30};
31
32struct TransScope {
33 TransScopeId id;
34 TransScope *parent;
35};
36
37struct TransScopeSwitch {
38 TransScope base;
39 AstNode *switch_node;
40 uint32_t case_index;
41 bool found_default;
42 Buf *end_label_name;
43};
44
45struct TransScopeVar {
46 TransScope base;
47 Buf *c_name;
48 Buf *zig_name;
49};
50
51struct TransScopeBlock {
52 TransScope base;
53 AstNode *node;
54};
55
56struct TransScopeRoot {
57 TransScope base;
58};
59
60struct TransScopeWhile {
61 TransScope base;
62 AstNode *node;
63};
64
65struct Context {
66 AstNode *root;
67 bool want_export;
68 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
69 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
70 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
71 ZigClangSourceManager *source_manager;
72 ZigList<Alias> aliases;
73 bool warnings_on;
74
75 CodeGen *codegen;
76 ZigClangASTContext *ctx;
77
78 TransScopeRoot *global_scope;
79 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
80};
81
82enum ResultUsed {
83 ResultUsedNo,
84 ResultUsedYes,
85};
86
87enum TransLRValue {
88 TransLValue,
89 TransRValue,
90};
91
92static TransScopeRoot *trans_scope_root_create(Context *c);
93static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope);
94static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope);
95static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name);
96static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope);
97
98static TransScopeBlock *trans_scope_block_find(TransScope *scope);
99
100static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl);
101static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl);
102static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl);
103
104static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt,
105 ResultUsed result_used, TransLRValue lrval,
106 AstNode **out_node, TransScope **out_child_scope,
107 TransScope **out_node_scope);
108static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node);
109static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval);
110static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc);
111static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc);
112static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope,
113 const ZigClangExpr *expr, TransLRValue lrval);
114static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt,
115 ZigClangSourceLocation source_loc);
116static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt);
117
118
119ATTRIBUTE_PRINTF(3, 4)
120static void emit_warning(Context *c, ZigClangSourceLocation sl, const char *format, ...) {
121 if (!c->warnings_on) {
122 return;
123 }
124
125 va_list ap;
126 va_start(ap, format);
127 Buf *msg = buf_vprintf(format, ap);
128 va_end(ap);
129
130 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
131 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
132 Buf *path;
133 if (filename_bytes) {
134 path = buf_create_from_str(filename_bytes);
135 } else {
136 path = buf_sprintf("(no file)");
137 }
138 unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
139 unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
140 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
141}
142
143static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) {
144 Alias *alias = c->aliases.add_one();
145 alias->new_name = new_name;
146 alias->canon_name = canon_name;
147}
148
149static Buf *trans_lookup_zig_symbol(Context *c, TransScope *scope, Buf *c_symbol_name) {
150 while (scope != nullptr) {
151 if (scope->id == TransScopeIdVar) {
152 TransScopeVar *var_scope = (TransScopeVar *)scope;
153 if (buf_eql_buf(var_scope->c_name, c_symbol_name)) {
154 return var_scope->zig_name;
155 }
156 }
157 scope = scope->parent;
158 }
159 return c_symbol_name;
160}
161
162static AstNode * trans_create_node(Context *c, NodeType id) {
163 AstNode *node = allocate<AstNode>(1);
164 node->type = id;
165 // TODO line/column. mapping to C file??
166 return node;
167}
168
169static AstNode *trans_create_node_break(Context *c, Buf *label_name, AstNode *value_node) {
170 AstNode *node = trans_create_node(c, NodeTypeBreak);
171 node->data.break_expr.name = label_name;
172 node->data.break_expr.expr = value_node;
173 return node;
174}
175
176static AstNode *trans_create_node_return(Context *c, AstNode *value_node) {
177 AstNode *node = trans_create_node(c, NodeTypeReturnExpr);
178 node->data.return_expr.kind = ReturnKindUnconditional;
179 node->data.return_expr.expr = value_node;
180 return node;
181}
182
183static AstNode *trans_create_node_if(Context *c, AstNode *cond_node, AstNode *then_node, AstNode *else_node) {
184 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
185 node->data.if_bool_expr.condition = cond_node;
186 node->data.if_bool_expr.then_block = then_node;
187 node->data.if_bool_expr.else_node = else_node;
188 return node;
189}
190
191static AstNode *trans_create_node_float_lit(Context *c, double value) {
192 AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
193 node->data.float_literal.bigfloat = allocate<BigFloat>(1);
194 bigfloat_init_64(node->data.float_literal.bigfloat, value);
195 return node;
196}
197
198static AstNode *trans_create_node_symbol(Context *c, Buf *name) {
199 AstNode *node = trans_create_node(c, NodeTypeSymbol);
200 node->data.symbol_expr.symbol = name;
201 return node;
202}
203
204static AstNode *trans_create_node_symbol_str(Context *c, const char *name) {
205 return trans_create_node_symbol(c, buf_create_from_str(name));
206}
207
208static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) {
209 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
210 node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name);
211 node->data.fn_call_expr.modifier = CallModifierBuiltin;
212 return node;
213}
214
215static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) {
216 return trans_create_node_builtin_fn_call(c, buf_create_from_str(name));
217}
218
219static AstNode *trans_create_node_opaque(Context *c) {
220 return trans_create_node_builtin_fn_call_str(c, "OpaqueType");
221}
222
223static AstNode *trans_create_node_cast(Context *c, AstNode *dest_type, AstNode *operand) {
224 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
225 node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, buf_create_from_str("as"));
226 node->data.fn_call_expr.modifier = CallModifierBuiltin;
227 node->data.fn_call_expr.params.append(dest_type);
228 node->data.fn_call_expr.params.append(operand);
229 return node;
230}
231
232static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) {
233 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
234 node->data.fn_call_expr.fn_ref_expr = fn_ref_expr;
235 node->data.fn_call_expr.params.append(arg1);
236 return node;
237}
238
239static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
240 AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr);
241 if (container->type == NodeTypeSymbol) {
242 assert(container->data.symbol_expr.symbol != nullptr);
243 }
244 node->data.field_access_expr.struct_expr = container;
245 node->data.field_access_expr.field_name = field_name;
246 return node;
247}
248
249static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) {
250 return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
251}
252
253static AstNode *trans_create_node_ptr_deref(Context *c, AstNode *child_node) {
254 AstNode *node = trans_create_node(c, NodeTypePtrDeref);
255 node->data.ptr_deref_expr.target = child_node;
256 return node;
257}
258
259static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
260 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
261 node->data.prefix_op_expr.prefix_op = op;
262 node->data.prefix_op_expr.primary_expr = child_node;
263 return node;
264}
265
266static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child_node) {
267 AstNode *node = trans_create_node(c, NodeTypeUnwrapOptional);
268 node->data.unwrap_optional.expr = child_node;
269 return node;
270}
271
272static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) {
273 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
274 node->data.bin_op_expr.op1 = lhs_node;
275 node->data.bin_op_expr.bin_op = op;
276 node->data.bin_op_expr.op2 = rhs_node;
277 return node;
278}
279
280static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNode *node) {
281 if (result_used == ResultUsedYes) return node;
282 return trans_create_node_bin_op(c,
283 trans_create_node_symbol_str(c, "_"),
284 BinOpTypeAssign,
285 node);
286}
287
288static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
289 switch (ptr_len) {
290 case PtrLenSingle:
291 return TokenIdStar;
292 case PtrLenUnknown:
293 return TokenIdLBracket;
294 case PtrLenC:
295 return TokenIdSymbol;
296 }
297 zig_unreachable();
298}
299
300static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
301 AstNode *node = trans_create_node(c, NodeTypePointerType);
302 node->data.pointer_type.star_token = allocate<ZigToken>(1);
303 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
304 node->data.pointer_type.is_const = is_const;
305 node->data.pointer_type.is_volatile = is_volatile;
306 node->data.pointer_type.op_expr = child_node;
307 return node;
308}
309
310static AstNode *trans_create_node_addr_of(Context *c, AstNode *child_node) {
311 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
312 node->data.prefix_op_expr.prefix_op = PrefixOpAddrOf;
313 node->data.prefix_op_expr.primary_expr = child_node;
314 return node;
315}
316
317static AstNode *trans_create_node_bool(Context *c, bool value) {
318 AstNode *bool_node = trans_create_node(c, NodeTypeBoolLiteral);
319 bool_node->data.bool_literal.value = value;
320 return bool_node;
321}
322
323static AstNode *trans_create_node_str_lit(Context *c, Buf *buf) {
324 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
325 node->data.string_literal.buf = buf;
326 return node;
327}
328
329static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {
330 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
331 node->data.int_literal.bigint = allocate<BigInt>(1);
332 bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative);
333 return node;
334}
335
336static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) {
337 return trans_create_node_unsigned_negative(c, x, false);
338}
339
340static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative,
341 const char *type_name)
342{
343 AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative);
344 return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node);
345}
346
347static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) {
348 AstNode *node = trans_create_node(c, NodeTypeArrayType);
349 node->data.array_type.size = size_node;
350 node->data.array_type.child_type = child_type_node;
351 return node;
352}
353
354static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool is_const, Buf *var_name,
355 AstNode *type_node, AstNode *init_node)
356{
357 AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration);
358 node->data.variable_declaration.visib_mod = visib_mod;
359 node->data.variable_declaration.symbol = var_name;
360 node->data.variable_declaration.is_const = is_const;
361 node->data.variable_declaration.type = type_node;
362 node->data.variable_declaration.expr = init_node;
363 return node;
364}
365
366static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
367 AstNode *init_node)
368{
369 return trans_create_node_var_decl(c, VisibModPub, is_const, var_name, type_node, init_node);
370}
371
372static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
373 AstNode *init_node)
374{
375 return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node);
376}
377
378static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, AstNode *ref_node, AstNode *src_proto_node) {
379 AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
380 AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
381 fn_proto->data.fn_proto.visib_mod = VisibModPub;
382 fn_proto->data.fn_proto.name = fn_name;
383 fn_proto->data.fn_proto.fn_inline = FnInlineAlways;
384 fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
385
386 fn_def->data.fn_def.fn_proto = fn_proto;
387 fn_proto->data.fn_proto.fn_def_node = fn_def;
388
389 AstNode *unwrap_node = trans_create_node_unwrap_null(c, ref_node);
390 AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr);
391 fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
392
393 for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) {
394 AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i);
395 Buf *param_name = src_param_node->data.param_decl.name;
396 if (!param_name) param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
397
398 AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl);
399 dest_param_node->data.param_decl.name = param_name;
400 dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type;
401 dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias;
402 fn_proto->data.fn_proto.params.append(dest_param_node);
403
404 fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name));
405
406 }
407
408 AstNode *block = trans_create_node(c, NodeTypeBlock);
409 block->data.block.statements.resize(1);
410 block->data.block.statements.items[0] = trans_create_node_return(c, fn_call_node);
411
412 fn_def->data.fn_def.body = block;
413 return fn_def;
414}
415
416static AstNode *trans_create_node_grouped_expr(Context *c, AstNode *child) {
417 AstNode *node = trans_create_node(c, NodeTypeGroupedExpr);
418 node->data.grouped_expr = child;
419 return node;
420}
421
422static AstNode *get_global(Context *c, Buf *name) {
423 {
424 auto entry = c->global_table.maybe_get(name);
425 if (entry) {
426 return entry->value;
427 }
428 }
429 {
430 auto entry = c->macro_table.maybe_get(name);
431 if (entry)
432 return entry->value;
433 }
434 ZigType *type;
435 if (get_primitive_type(c->codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
436 return trans_create_node_symbol(c, name);
437 }
438 return nullptr;
439}
440
441static void add_top_level_decl(Context *c, Buf *name, AstNode *node) {
442 c->global_table.put(name, node);
443 c->root->data.container_decl.decls.append(node);
444}
445
446static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
447 bool is_const = true;
448 AstNode *type_node = nullptr;
449 AstNode *node = trans_create_node_var_decl_global(c, is_const, var_name, type_node, value_node);
450 add_top_level_decl(c, var_name, node);
451 return node;
452}
453
454static AstNode *trans_create_node_apint(Context *c, const ZigClangAPSInt *aps_int) {
455 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
456 node->data.int_literal.bigint = allocate<BigInt>(1);
457 bool is_negative = ZigClangAPSInt_isSigned(aps_int) && ZigClangAPSInt_isNegative(aps_int);
458 if (!is_negative) {
459 bigint_init_data(node->data.int_literal.bigint,
460 ZigClangAPSInt_getRawData(aps_int),
461 ZigClangAPSInt_getNumWords(aps_int),
462 false);
463 return node;
464 }
465 const ZigClangAPSInt *negated = ZigClangAPSInt_negate(aps_int);
466 bigint_init_data(node->data.int_literal.bigint, ZigClangAPSInt_getRawData(negated),
467 ZigClangAPSInt_getNumWords(negated), true);
468 ZigClangAPSInt_free(negated);
469 return node;
470}
471
472static AstNode *trans_create_node_apfloat(Context *c, const ZigClangAPFloat *ap_float) {
473 uint8_t buf[128];
474 size_t written = ZigClangAPFloat_convertToHexString(ap_float, (char *)buf, 0, false,
475 ZigClangAPFloat_roundingMode_NearestTiesToEven);
476 AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
477 node->data.float_literal.bigfloat = allocate<BigFloat>(1);
478 if (bigfloat_init_buf(node->data.float_literal.bigfloat, buf, written)) {
479 node->data.float_literal.overflow = true;
480 }
481 return node;
482}
483
484static const ZigClangType *qual_type_canon(ZigClangQualType qt) {
485 ZigClangQualType canon = ZigClangQualType_getCanonicalType(qt);
486 return ZigClangQualType_getTypePtr(canon);
487}
488
489static ZigClangQualType get_expr_qual_type(Context *c, const ZigClangExpr *expr) {
490 // String literals in C are `char *` but they should really be `const char *`.
491 if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) {
492 const ZigClangImplicitCastExpr *cast_expr = reinterpret_cast<const ZigClangImplicitCastExpr *>(expr);
493 if (ZigClangImplicitCastExpr_getCastKind(cast_expr) == ZigClangCK_ArrayToPointerDecay) {
494 const ZigClangExpr *sub_expr = ZigClangImplicitCastExpr_getSubExpr(cast_expr);
495 if (ZigClangExpr_getStmtClass(sub_expr) == ZigClangStmt_StringLiteralClass) {
496 ZigClangQualType array_qt = ZigClangExpr_getType(sub_expr);
497 const ZigClangArrayType *array_type = reinterpret_cast<const ZigClangArrayType *>(
498 ZigClangQualType_getTypePtr(array_qt));
499 ZigClangQualType pointee_qt = ZigClangArrayType_getElementType(array_type);
500 ZigClangQualType_addConst(&pointee_qt);
501 return ZigClangASTContext_getPointerType(c->ctx, pointee_qt);
502 }
503 }
504 }
505 return ZigClangExpr_getType(expr);
506}
507
508static ZigClangQualType get_expr_qual_type_before_implicit_cast(Context *c, const ZigClangExpr *expr) {
509 if (ZigClangExpr_getStmtClass(expr) == ZigClangStmt_ImplicitCastExprClass) {
510 const ZigClangImplicitCastExpr *cast_expr = reinterpret_cast<const ZigClangImplicitCastExpr *>(expr);
511 return get_expr_qual_type(c, ZigClangImplicitCastExpr_getSubExpr(cast_expr));
512 }
513 return ZigClangExpr_getType(expr);
514}
515
516static AstNode *get_expr_type(Context *c, const ZigClangExpr *expr) {
517 return trans_qual_type(c, get_expr_qual_type(c, expr), ZigClangExpr_getBeginLoc(expr));
518}
519
520static bool is_c_void_type(AstNode *node) {
521 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
522}
523
524static bool qual_type_is_ptr(ZigClangQualType qt) {
525 const ZigClangType *ty = qual_type_canon(qt);
526 return ZigClangType_getTypeClass(ty) == ZigClangType_Pointer;
527}
528
529static const ZigClangFunctionProtoType *qual_type_get_fn_proto(ZigClangQualType qt, bool *is_ptr) {
530 const ZigClangType *ty = qual_type_canon(qt);
531 *is_ptr = false;
532
533 if (ZigClangType_getTypeClass(ty) == ZigClangType_Pointer) {
534 *is_ptr = true;
535 ZigClangQualType child_qt = ZigClangType_getPointeeType(ty);
536 ty = ZigClangQualType_getTypePtr(child_qt);
537 }
538
539 if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionProto) {
540 return reinterpret_cast<const ZigClangFunctionProtoType*>(ty);
541 }
542
543 return nullptr;
544}
545
546static bool qual_type_is_fn_ptr(ZigClangQualType qt) {
547 bool is_ptr;
548 if (qual_type_get_fn_proto(qt, &is_ptr)) {
549 return is_ptr;
550 }
551
552 return false;
553}
554
555static uint32_t qual_type_int_bit_width(Context *c, const ZigClangQualType qt, ZigClangSourceLocation source_loc) {
556 const ZigClangType *ty = ZigClangQualType_getTypePtr(qt);
557 switch (ZigClangType_getTypeClass(ty)) {
558 case ZigClangType_Builtin:
559 {
560 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
561 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
562 case ZigClangBuiltinTypeChar_U:
563 case ZigClangBuiltinTypeUChar:
564 case ZigClangBuiltinTypeChar_S:
565 case ZigClangBuiltinTypeSChar:
566 return 8;
567 case ZigClangBuiltinTypeUInt128:
568 case ZigClangBuiltinTypeInt128:
569 return 128;
570 default:
571 return 0;
572 }
573 zig_unreachable();
574 }
575 case ZigClangType_Typedef:
576 {
577 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
578 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
579 const char *type_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl);
580 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
581 return 8;
582 } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {
583 return 16;
584 } else if (strcmp(type_name, "uint32_t") == 0 || strcmp(type_name, "int32_t") == 0) {
585 return 32;
586 } else if (strcmp(type_name, "uint64_t") == 0 || strcmp(type_name, "int64_t") == 0) {
587 return 64;
588 } else {
589 return 0;
590 }
591 }
592 default:
593 return 0;
594 }
595 zig_unreachable();
596}
597
598
599static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
600 ZigClangSourceLocation source_loc)
601{
602 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
603 if (int_bit_width != 0) {
604 // we can perform the log2 now.
605 uint64_t cast_bit_width = log2_u64(int_bit_width);
606 return trans_create_node_symbol(c, buf_sprintf("u%" ZIG_PRI_u64, cast_bit_width));
607 }
608
609 AstNode *zig_type_node = trans_qual_type(c, qt, source_loc);
610
611// @import("std").math.Log2Int(c_long);
612//
613// FnCall
614// FieldAccess
615// FieldAccess
616// FnCall (.builtin = true)
617// Symbol "import"
618// ZigClangStringLiteral "std"
619// Symbol "math"
620// Symbol "Log2Int"
621// zig_type_node
622
623 AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
624 import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit(c, buf_create_from_str("std")));
625 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
626 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
627 AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
628
629 return log2int_fn_call;
630}
631
632static bool qual_type_child_is_fn_proto(ZigClangQualType qt) {
633 const ZigClangType *ty = ZigClangQualType_getTypePtr(qt);
634 if (ZigClangType_getTypeClass(ty) == ZigClangType_Paren) {
635 const ZigClangParenType *paren_type = reinterpret_cast<const ZigClangParenType *>(ty);
636 ZigClangQualType inner_type = ZigClangParenType_getInnerType(paren_type);
637 if (ZigClangQualType_getTypeClass(inner_type) == ZigClangType_FunctionProto) {
638 return true;
639 }
640 } else if (ZigClangType_getTypeClass(ty) == ZigClangType_Attributed) {
641 const ZigClangAttributedType *attr_type = reinterpret_cast<const ZigClangAttributedType *>(ty);
642 return qual_type_child_is_fn_proto(ZigClangAttributedType_getEquivalentType(attr_type));
643 }
644 return false;
645}
646
647static AstNode* trans_c_ptr_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type,
648 ZigClangQualType src_type, AstNode *expr)
649{
650 const ZigClangType *ty = ZigClangQualType_getTypePtr(dest_type);
651 const ZigClangQualType child_type = ZigClangType_getPointeeType(ty);
652
653 AstNode *dest_type_node = trans_type(c, ty, source_location);
654 AstNode *child_type_node = trans_qual_type(c, child_type, source_location);
655
656 // Implicit downcasting from higher to lower alignment values is forbidden,
657 // use @alignCast to side-step this problem
658 AstNode *ptrcast_node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
659 ptrcast_node->data.fn_call_expr.params.append(dest_type_node);
660
661 if (ZigClangType_isVoidType(qual_type_canon(child_type))) {
662 // void has 1-byte alignment
663 ptrcast_node->data.fn_call_expr.params.append(expr);
664 } else {
665 AstNode *alignof_node = trans_create_node_builtin_fn_call_str(c, "alignOf");
666 alignof_node->data.fn_call_expr.params.append(child_type_node);
667 AstNode *aligncast_node = trans_create_node_builtin_fn_call_str(c, "alignCast");
668 aligncast_node->data.fn_call_expr.params.append(alignof_node);
669 aligncast_node->data.fn_call_expr.params.append(expr);
670
671 ptrcast_node->data.fn_call_expr.params.append(aligncast_node);
672 }
673
674 return ptrcast_node;
675}
676
677static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, ZigClangQualType dest_type,
678 ZigClangQualType src_type, AstNode *expr)
679{
680 // The only way void pointer casts are valid C code, is if
681 // the value of the expression is ignored. We therefore just
682 // return the expr, and let the system that ignores values
683 // translate this correctly.
684 if (ZigClangType_isVoidType(qual_type_canon(dest_type))) {
685 return expr;
686 }
687 if (ZigClangQualType_eq(dest_type, src_type)) {
688 return expr;
689 }
690 if (qual_type_is_ptr(dest_type) && qual_type_is_ptr(src_type)) {
691 return trans_c_ptr_cast(c, source_location, dest_type, src_type, expr);
692 }
693 if (c_is_unsigned_integer(c, dest_type) && qual_type_is_ptr(src_type)) {
694 AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
695 addr_node->data.fn_call_expr.params.append(expr);
696 return trans_create_node_cast(c, trans_qual_type(c, dest_type, source_location), addr_node);
697 }
698 if (c_is_unsigned_integer(c, src_type) && qual_type_is_ptr(dest_type)) {
699 AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
700 ptr_node->data.fn_call_expr.params.append(trans_qual_type(c, dest_type, source_location));
701 ptr_node->data.fn_call_expr.params.append(expr);
702 return ptr_node;
703 }
704 // TODO: maybe widen to increase size
705 // TODO: maybe bitcast to change sign
706 // TODO: maybe truncate to reduce size
707 return trans_create_node_cast(c, trans_qual_type(c, dest_type, source_location), expr);
708}
709
710static bool c_is_signed_integer(Context *c, ZigClangQualType qt) {
711 const ZigClangType *c_type = qual_type_canon(qt);
712 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
713 return false;
714 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
715 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
716 case ZigClangBuiltinTypeSChar:
717 case ZigClangBuiltinTypeShort:
718 case ZigClangBuiltinTypeInt:
719 case ZigClangBuiltinTypeLong:
720 case ZigClangBuiltinTypeLongLong:
721 case ZigClangBuiltinTypeInt128:
722 case ZigClangBuiltinTypeWChar_S:
723 return true;
724 default:
725 return false;
726 }
727}
728
729static bool c_is_unsigned_integer(Context *c, ZigClangQualType qt) {
730 const ZigClangType *c_type = qual_type_canon(qt);
731 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
732 return false;
733 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
734 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
735 case ZigClangBuiltinTypeChar_U:
736 case ZigClangBuiltinTypeUChar:
737 case ZigClangBuiltinTypeChar_S:
738 case ZigClangBuiltinTypeUShort:
739 case ZigClangBuiltinTypeUInt:
740 case ZigClangBuiltinTypeULong:
741 case ZigClangBuiltinTypeULongLong:
742 case ZigClangBuiltinTypeUInt128:
743 case ZigClangBuiltinTypeWChar_U:
744 return true;
745 default:
746 return false;
747 }
748}
749
750static bool c_is_builtin_type(Context *c, ZigClangQualType qt, ZigClangBuiltinTypeKind kind) {
751 const ZigClangType *c_type = qual_type_canon(qt);
752 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
753 return false;
754 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
755 return ZigClangBuiltinType_getKind(builtin_ty) == kind;
756}
757
758static bool c_is_float(Context *c, ZigClangQualType qt) {
759 const ZigClangType *c_type = ZigClangQualType_getTypePtr(qt);
760 if (ZigClangType_getTypeClass(c_type) != ZigClangType_Builtin)
761 return false;
762 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(c_type);
763 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
764 case ZigClangBuiltinTypeHalf:
765 case ZigClangBuiltinTypeFloat:
766 case ZigClangBuiltinTypeDouble:
767 case ZigClangBuiltinTypeFloat128:
768 case ZigClangBuiltinTypeLongDouble:
769 return true;
770 default:
771 return false;
772 }
773}
774
775static bool qual_type_has_wrapping_overflow(Context *c, ZigClangQualType qt) {
776 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
777 // float and signed integer overflow is undefined behavior.
778 return false;
779 } else {
780 // unsigned integer overflow wraps around.
781 return true;
782 }
783}
784
785static bool type_is_function(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
786 switch (ZigClangType_getTypeClass(ty)) {
787 case ZigClangType_FunctionProto:
788 case ZigClangType_FunctionNoProto:
789 return true;
790 case ZigClangType_Elaborated: {
791 const ZigClangElaboratedType *elaborated_ty = reinterpret_cast<const ZigClangElaboratedType*>(ty);
792 ZigClangQualType qt = ZigClangElaboratedType_getNamedType(elaborated_ty);
793 return type_is_function(c, ZigClangQualType_getTypePtr(qt), source_loc);
794 }
795 case ZigClangType_Typedef: {
796 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
797 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
798 ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
799 return type_is_function(c, ZigClangQualType_getTypePtr(underlying_type), source_loc);
800 }
801 default:
802 return false;
803 }
804}
805
806static bool type_is_opaque(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
807 switch (ZigClangType_getTypeClass(ty)) {
808 case ZigClangType_Builtin: {
809 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
810 return ZigClangBuiltinType_getKind(builtin_ty) == ZigClangBuiltinTypeVoid;
811 }
812 case ZigClangType_Record: {
813 const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty);
814 const ZigClangRecordDecl *record_decl = ZigClangRecordType_getDecl(record_ty);
815 const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl);
816 if (record_def == nullptr) {
817 return true;
818 }
819 for (ZigClangRecordDecl_field_iterator it = ZigClangRecordDecl_field_begin(record_def),
820 it_end = ZigClangRecordDecl_field_end(record_def);
821 ZigClangRecordDecl_field_iterator_neq(it, it_end);
822 it = ZigClangRecordDecl_field_iterator_next(it))
823 {
824 const ZigClangFieldDecl *field_decl = ZigClangRecordDecl_field_iterator_deref(it);
825
826 if (ZigClangFieldDecl_isBitField(field_decl)) {
827 return true;
828 }
829 }
830 return false;
831 }
832 case ZigClangType_Elaborated: {
833 const ZigClangElaboratedType *elaborated_ty = reinterpret_cast<const ZigClangElaboratedType*>(ty);
834 ZigClangQualType qt = ZigClangElaboratedType_getNamedType(elaborated_ty);
835 return type_is_opaque(c, ZigClangQualType_getTypePtr(qt), source_loc);
836 }
837 case ZigClangType_Typedef: {
838 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
839 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
840 ZigClangQualType underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
841 return type_is_opaque(c, ZigClangQualType_getTypePtr(underlying_type), source_loc);
842 }
843 default:
844 return false;
845 }
846}
847
848static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLocation source_loc) {
849 switch (ZigClangType_getTypeClass(ty)) {
850 case ZigClangType_Builtin:
851 {
852 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType *>(ty);
853 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
854 case ZigClangBuiltinTypeVoid:
855 return trans_create_node_symbol_str(c, "c_void");
856 case ZigClangBuiltinTypeBool:
857 return trans_create_node_symbol_str(c, "bool");
858 case ZigClangBuiltinTypeChar_U:
859 case ZigClangBuiltinTypeUChar:
860 case ZigClangBuiltinTypeChar_S:
861 case ZigClangBuiltinTypeChar8:
862 return trans_create_node_symbol_str(c, "u8");
863 case ZigClangBuiltinTypeSChar:
864 return trans_create_node_symbol_str(c, "i8");
865 case ZigClangBuiltinTypeUShort:
866 return trans_create_node_symbol_str(c, "c_ushort");
867 case ZigClangBuiltinTypeUInt:
868 return trans_create_node_symbol_str(c, "c_uint");
869 case ZigClangBuiltinTypeULong:
870 return trans_create_node_symbol_str(c, "c_ulong");
871 case ZigClangBuiltinTypeULongLong:
872 return trans_create_node_symbol_str(c, "c_ulonglong");
873 case ZigClangBuiltinTypeShort:
874 return trans_create_node_symbol_str(c, "c_short");
875 case ZigClangBuiltinTypeInt:
876 return trans_create_node_symbol_str(c, "c_int");
877 case ZigClangBuiltinTypeLong:
878 return trans_create_node_symbol_str(c, "c_long");
879 case ZigClangBuiltinTypeLongLong:
880 return trans_create_node_symbol_str(c, "c_longlong");
881 case ZigClangBuiltinTypeUInt128:
882 return trans_create_node_symbol_str(c, "u128");
883 case ZigClangBuiltinTypeInt128:
884 return trans_create_node_symbol_str(c, "i128");
885 case ZigClangBuiltinTypeFloat:
886 return trans_create_node_symbol_str(c, "f32");
887 case ZigClangBuiltinTypeDouble:
888 return trans_create_node_symbol_str(c, "f64");
889 case ZigClangBuiltinTypeFloat128:
890 return trans_create_node_symbol_str(c, "f128");
891 case ZigClangBuiltinTypeFloat16:
892 return trans_create_node_symbol_str(c, "f16");
893 case ZigClangBuiltinTypeLongDouble:
894 return trans_create_node_symbol_str(c, "c_longdouble");
895 case ZigClangBuiltinTypeWChar_U:
896 case ZigClangBuiltinTypeChar16:
897 case ZigClangBuiltinTypeChar32:
898 case ZigClangBuiltinTypeWChar_S:
899 case ZigClangBuiltinTypeHalf:
900 case ZigClangBuiltinTypeNullPtr:
901 case ZigClangBuiltinTypeObjCId:
902 case ZigClangBuiltinTypeObjCClass:
903 case ZigClangBuiltinTypeObjCSel:
904 case ZigClangBuiltinTypeOMPArraySection:
905 case ZigClangBuiltinTypeDependent:
906 case ZigClangBuiltinTypeOverload:
907 case ZigClangBuiltinTypeBoundMember:
908 case ZigClangBuiltinTypePseudoObject:
909 case ZigClangBuiltinTypeUnknownAny:
910 case ZigClangBuiltinTypeBuiltinFn:
911 case ZigClangBuiltinTypeARCUnbridgedCast:
912 case ZigClangBuiltinTypeShortAccum:
913 case ZigClangBuiltinTypeAccum:
914 case ZigClangBuiltinTypeLongAccum:
915 case ZigClangBuiltinTypeUShortAccum:
916 case ZigClangBuiltinTypeUAccum:
917 case ZigClangBuiltinTypeULongAccum:
918
919 case ZigClangBuiltinTypeOCLImage1dRO:
920 case ZigClangBuiltinTypeOCLImage1dArrayRO:
921 case ZigClangBuiltinTypeOCLImage1dBufferRO:
922 case ZigClangBuiltinTypeOCLImage2dRO:
923 case ZigClangBuiltinTypeOCLImage2dArrayRO:
924 case ZigClangBuiltinTypeOCLImage2dDepthRO:
925 case ZigClangBuiltinTypeOCLImage2dArrayDepthRO:
926 case ZigClangBuiltinTypeOCLImage2dMSAARO:
927 case ZigClangBuiltinTypeOCLImage2dArrayMSAARO:
928 case ZigClangBuiltinTypeOCLImage2dMSAADepthRO:
929 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO:
930 case ZigClangBuiltinTypeOCLImage3dRO:
931 case ZigClangBuiltinTypeOCLImage1dWO:
932 case ZigClangBuiltinTypeOCLImage1dArrayWO:
933 case ZigClangBuiltinTypeOCLImage1dBufferWO:
934 case ZigClangBuiltinTypeOCLImage2dWO:
935 case ZigClangBuiltinTypeOCLImage2dArrayWO:
936 case ZigClangBuiltinTypeOCLImage2dDepthWO:
937 case ZigClangBuiltinTypeOCLImage2dArrayDepthWO:
938 case ZigClangBuiltinTypeOCLImage2dMSAAWO:
939 case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO:
940 case ZigClangBuiltinTypeOCLImage2dMSAADepthWO:
941 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO:
942 case ZigClangBuiltinTypeOCLImage3dWO:
943 case ZigClangBuiltinTypeOCLImage1dRW:
944 case ZigClangBuiltinTypeOCLImage1dArrayRW:
945 case ZigClangBuiltinTypeOCLImage1dBufferRW:
946 case ZigClangBuiltinTypeOCLImage2dRW:
947 case ZigClangBuiltinTypeOCLImage2dArrayRW:
948 case ZigClangBuiltinTypeOCLImage2dDepthRW:
949 case ZigClangBuiltinTypeOCLImage2dArrayDepthRW:
950 case ZigClangBuiltinTypeOCLImage2dMSAARW:
951 case ZigClangBuiltinTypeOCLImage2dArrayMSAARW:
952 case ZigClangBuiltinTypeOCLImage2dMSAADepthRW:
953 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW:
954 case ZigClangBuiltinTypeOCLImage3dRW:
955 case ZigClangBuiltinTypeOCLSampler:
956 case ZigClangBuiltinTypeOCLEvent:
957 case ZigClangBuiltinTypeOCLClkEvent:
958 case ZigClangBuiltinTypeOCLQueue:
959 case ZigClangBuiltinTypeOCLReserveID:
960 case ZigClangBuiltinTypeShortFract:
961 case ZigClangBuiltinTypeFract:
962 case ZigClangBuiltinTypeLongFract:
963 case ZigClangBuiltinTypeUShortFract:
964 case ZigClangBuiltinTypeUFract:
965 case ZigClangBuiltinTypeULongFract:
966 case ZigClangBuiltinTypeSatShortAccum:
967 case ZigClangBuiltinTypeSatAccum:
968 case ZigClangBuiltinTypeSatLongAccum:
969 case ZigClangBuiltinTypeSatUShortAccum:
970 case ZigClangBuiltinTypeSatUAccum:
971 case ZigClangBuiltinTypeSatULongAccum:
972 case ZigClangBuiltinTypeSatShortFract:
973 case ZigClangBuiltinTypeSatFract:
974 case ZigClangBuiltinTypeSatLongFract:
975 case ZigClangBuiltinTypeSatUShortFract:
976 case ZigClangBuiltinTypeSatUFract:
977 case ZigClangBuiltinTypeSatULongFract:
978 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload:
979 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload:
980 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload:
981 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload:
982 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult:
983 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult:
984 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult:
985 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult:
986 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout:
987 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout:
988 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin:
989 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin:
990 emit_warning(c, source_loc, "unsupported builtin type");
991 return nullptr;
992 }
993 break;
994 }
995 case ZigClangType_Pointer:
996 {
997 ZigClangQualType child_qt = ZigClangType_getPointeeType(ty);
998 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
999 if (child_node == nullptr) {
1000 emit_warning(c, source_loc, "pointer to unsupported type");
1001 return nullptr;
1002 }
1003
1004 if (qual_type_child_is_fn_proto(child_qt)) {
1005 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
1006 }
1007
1008 if (type_is_function(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
1009 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
1010 } else if (type_is_opaque(c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
1011 AstNode *pointer_node = trans_create_node_ptr_type(c,
1012 ZigClangQualType_isConstQualified(child_qt),
1013 ZigClangQualType_isVolatileQualified(child_qt),
1014 child_node, PtrLenSingle);
1015 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
1016 } else {
1017 return trans_create_node_ptr_type(c,
1018 ZigClangQualType_isConstQualified(child_qt),
1019 ZigClangQualType_isVolatileQualified(child_qt),
1020 child_node, PtrLenC);
1021 }
1022 }
1023 case ZigClangType_Typedef:
1024 {
1025 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
1026 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1027 return resolve_typedef_decl(c, typedef_decl);
1028 }
1029 case ZigClangType_Elaborated:
1030 {
1031 const ZigClangElaboratedType *elaborated_ty = reinterpret_cast<const ZigClangElaboratedType*>(ty);
1032 switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) {
1033 case ZigClangETK_Struct:
1034 case ZigClangETK_Enum:
1035 case ZigClangETK_Union:
1036 return trans_qual_type(c, ZigClangElaboratedType_getNamedType(elaborated_ty), source_loc);
1037 case ZigClangETK_Interface:
1038 case ZigClangETK_Class:
1039 case ZigClangETK_Typename:
1040 case ZigClangETK_None:
1041 emit_warning(c, source_loc, "unsupported elaborated type");
1042 return nullptr;
1043 }
1044 }
1045 case ZigClangType_FunctionProto:
1046 case ZigClangType_FunctionNoProto:
1047 {
1048 const ZigClangFunctionType *fn_ty = reinterpret_cast<const ZigClangFunctionType*>(ty);
1049
1050 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
1051 switch (ZigClangFunctionType_getCallConv(fn_ty)) {
1052 case ZigClangCallingConv_C: // __attribute__((cdecl))
1053 proto_node->data.fn_proto.cc = CallingConventionC;
1054 proto_node->data.fn_proto.is_extern = true;
1055 break;
1056 case ZigClangCallingConv_X86StdCall: // __attribute__((stdcall))
1057 proto_node->data.fn_proto.cc = CallingConventionStdcall;
1058 break;
1059 case ZigClangCallingConv_X86FastCall: // __attribute__((fastcall))
1060 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
1061 return nullptr;
1062 case ZigClangCallingConv_X86ThisCall: // __attribute__((thiscall))
1063 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
1064 return nullptr;
1065 case ZigClangCallingConv_X86VectorCall: // __attribute__((vectorcall))
1066 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
1067 return nullptr;
1068 case ZigClangCallingConv_X86Pascal: // __attribute__((pascal))
1069 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
1070 return nullptr;
1071 case ZigClangCallingConv_Win64: // __attribute__((ms_abi))
1072 emit_warning(c, source_loc, "unsupported calling convention: win64");
1073 return nullptr;
1074 case ZigClangCallingConv_X86_64SysV: // __attribute__((sysv_abi))
1075 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
1076 return nullptr;
1077 case ZigClangCallingConv_X86RegCall:
1078 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
1079 return nullptr;
1080 case ZigClangCallingConv_AAPCS: // __attribute__((pcs("aapcs")))
1081 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
1082 return nullptr;
1083 case ZigClangCallingConv_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
1084 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
1085 return nullptr;
1086 case ZigClangCallingConv_IntelOclBicc: // __attribute__((intel_ocl_bicc))
1087 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
1088 return nullptr;
1089 case ZigClangCallingConv_SpirFunction: // default for OpenCL functions on SPIR target
1090 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
1091 return nullptr;
1092 case ZigClangCallingConv_OpenCLKernel:
1093 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
1094 return nullptr;
1095 case ZigClangCallingConv_Swift:
1096 emit_warning(c, source_loc, "unsupported calling convention: Swift");
1097 return nullptr;
1098 case ZigClangCallingConv_PreserveMost:
1099 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
1100 return nullptr;
1101 case ZigClangCallingConv_PreserveAll:
1102 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
1103 return nullptr;
1104 case ZigClangCallingConv_AArch64VectorCall:
1105 emit_warning(c, source_loc, "unsupported calling convention: AArch64VectorCall");
1106 return nullptr;
1107 }
1108
1109 if (ZigClangFunctionType_getNoReturnAttr(fn_ty)) {
1110 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
1111 } else {
1112 proto_node->data.fn_proto.return_type = trans_qual_type(c,
1113 ZigClangFunctionType_getReturnType(fn_ty), source_loc);
1114 if (proto_node->data.fn_proto.return_type == nullptr) {
1115 emit_warning(c, source_loc, "unsupported function proto return type");
1116 return nullptr;
1117 }
1118 // convert c_void to actual void (only for return type)
1119 // we do want to look at the AstNode instead of ZigClangQualType, because
1120 // if they do something like:
1121 // typedef Foo void;
1122 // void foo(void) -> Foo;
1123 // we want to keep the return type AST node.
1124 if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
1125 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "void");
1126 }
1127 }
1128
1129 //emit_warning(c, source_loc, "TODO figure out fn prototype fn name");
1130 const char *fn_name = nullptr;
1131 if (fn_name != nullptr) {
1132 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
1133 }
1134
1135 if (ZigClangType_getTypeClass(ty) == ZigClangType_FunctionNoProto) {
1136 return proto_node;
1137 }
1138
1139 const ZigClangFunctionProtoType *fn_proto_ty = reinterpret_cast<const ZigClangFunctionProtoType*>(ty);
1140
1141 proto_node->data.fn_proto.is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
1142 size_t param_count = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
1143
1144 for (size_t i = 0; i < param_count; i += 1) {
1145 ZigClangQualType qt = ZigClangFunctionProtoType_getParamType(fn_proto_ty, i);
1146 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
1147
1148 if (param_type_node == nullptr) {
1149 emit_warning(c, source_loc, "unresolved function proto parameter type");
1150 return nullptr;
1151 }
1152
1153 AstNode *param_node = trans_create_node(c, NodeTypeParamDecl);
1154 //emit_warning(c, source_loc, "TODO figure out fn prototype param name");
1155 const char *param_name = nullptr;
1156 if (param_name != nullptr) {
1157 param_node->data.param_decl.name = buf_create_from_str(param_name);
1158 }
1159 param_node->data.param_decl.is_noalias = ZigClangQualType_isRestrictQualified(qt);
1160 param_node->data.param_decl.type = param_type_node;
1161 proto_node->data.fn_proto.params.append(param_node);
1162 }
1163 // TODO check for always_inline attribute
1164 // TODO check for align attribute
1165
1166 return proto_node;
1167 }
1168 case ZigClangType_Record:
1169 {
1170 const ZigClangRecordType *record_ty = reinterpret_cast<const ZigClangRecordType*>(ty);
1171 return resolve_record_decl(c, ZigClangRecordType_getDecl(record_ty));
1172 }
1173 case ZigClangType_Enum:
1174 {
1175 const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType*>(ty);
1176 return resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty));
1177 }
1178 case ZigClangType_ConstantArray:
1179 {
1180 const ZigClangConstantArrayType *const_arr_ty = reinterpret_cast<const ZigClangConstantArrayType *>(ty);
1181 AstNode *child_type_node = trans_qual_type(c,
1182 ZigClangConstantArrayType_getElementType(const_arr_ty), source_loc);
1183 if (child_type_node == nullptr) {
1184 emit_warning(c, source_loc, "unresolved array element type");
1185 return nullptr;
1186 }
1187 const ZigClangAPInt *size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
1188 uint64_t size = ZigClangAPInt_getLimitedValue(size_ap_int, UINT64_MAX);
1189 AstNode *size_node = trans_create_node_unsigned(c, size);
1190 return trans_create_node_array_type(c, size_node, child_type_node);
1191 }
1192 case ZigClangType_Paren:
1193 {
1194 const ZigClangParenType *paren_ty = reinterpret_cast<const ZigClangParenType *>(ty);
1195 return trans_qual_type(c, ZigClangParenType_getInnerType(paren_ty), source_loc);
1196 }
1197 case ZigClangType_Decayed:
1198 {
1199 const ZigClangDecayedType *decayed_ty = reinterpret_cast<const ZigClangDecayedType *>(ty);
1200 return trans_qual_type(c, ZigClangDecayedType_getDecayedType(decayed_ty), source_loc);
1201 }
1202 case ZigClangType_Attributed:
1203 {
1204 const ZigClangAttributedType *attributed_ty = reinterpret_cast<const ZigClangAttributedType *>(ty);
1205 return trans_qual_type(c, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc);
1206 }
1207 case ZigClangType_MacroQualified:
1208 {
1209 const ZigClangMacroQualifiedType *macroqualified_ty = reinterpret_cast<const ZigClangMacroQualifiedType *>(ty);
1210 return trans_qual_type(c, ZigClangMacroQualifiedType_getModifiedType(macroqualified_ty), source_loc);
1211 }
1212 case ZigClangType_IncompleteArray:
1213 {
1214 const ZigClangIncompleteArrayType *incomplete_array_ty = reinterpret_cast<const ZigClangIncompleteArrayType *>(ty);
1215 ZigClangQualType child_qt = ZigClangIncompleteArrayType_getElementType(incomplete_array_ty);
1216 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
1217 if (child_type_node == nullptr) {
1218 emit_warning(c, source_loc, "unresolved array element type");
1219 return nullptr;
1220 }
1221 AstNode *pointer_node = trans_create_node_ptr_type(c,
1222 ZigClangQualType_isConstQualified(child_qt),
1223 ZigClangQualType_isVolatileQualified(child_qt),
1224 child_type_node, PtrLenC);
1225 return pointer_node;
1226 }
1227 case ZigClangType_BlockPointer:
1228 case ZigClangType_LValueReference:
1229 case ZigClangType_RValueReference:
1230 case ZigClangType_MemberPointer:
1231 case ZigClangType_VariableArray:
1232 case ZigClangType_DependentSizedArray:
1233 case ZigClangType_DependentSizedExtVector:
1234 case ZigClangType_Vector:
1235 case ZigClangType_ExtVector:
1236 case ZigClangType_UnresolvedUsing:
1237 case ZigClangType_Adjusted:
1238 case ZigClangType_TypeOfExpr:
1239 case ZigClangType_TypeOf:
1240 case ZigClangType_Decltype:
1241 case ZigClangType_UnaryTransform:
1242 case ZigClangType_TemplateTypeParm:
1243 case ZigClangType_SubstTemplateTypeParm:
1244 case ZigClangType_SubstTemplateTypeParmPack:
1245 case ZigClangType_TemplateSpecialization:
1246 case ZigClangType_Auto:
1247 case ZigClangType_InjectedClassName:
1248 case ZigClangType_DependentName:
1249 case ZigClangType_DependentTemplateSpecialization:
1250 case ZigClangType_PackExpansion:
1251 case ZigClangType_ObjCObject:
1252 case ZigClangType_ObjCInterface:
1253 case ZigClangType_Complex:
1254 case ZigClangType_ObjCObjectPointer:
1255 case ZigClangType_Atomic:
1256 case ZigClangType_Pipe:
1257 case ZigClangType_ObjCTypeParam:
1258 case ZigClangType_DeducedTemplateSpecialization:
1259 case ZigClangType_DependentAddressSpace:
1260 case ZigClangType_DependentVector:
1261 emit_warning(c, source_loc, "unsupported type: '%s'", ZigClangType_getTypeClassName(ty));
1262 return nullptr;
1263 }
1264 zig_unreachable();
1265}
1266
1267static AstNode *trans_qual_type(Context *c, ZigClangQualType qt, ZigClangSourceLocation source_loc) {
1268 return trans_type(c, ZigClangQualType_getTypePtr(qt), source_loc);
1269}
1270
1271static int trans_compound_stmt_inline(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
1272 AstNode *block_node, TransScope **out_node_scope)
1273{
1274 assert(block_node->type == NodeTypeBlock);
1275 for (ZigClangCompoundStmt_const_body_iterator it = ZigClangCompoundStmt_body_begin(stmt),
1276 end_it = ZigClangCompoundStmt_body_end(stmt); it != end_it; ++it)
1277 {
1278 AstNode *child_node;
1279 scope = trans_stmt(c, scope, *it, &child_node);
1280 if (scope == nullptr)
1281 return ErrorUnexpected;
1282 if (child_node != nullptr)
1283 block_node->data.block.statements.append(child_node);
1284 }
1285 if (out_node_scope != nullptr) {
1286 *out_node_scope = scope;
1287 }
1288 return ErrorNone;
1289}
1290
1291static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const ZigClangCompoundStmt *stmt,
1292 TransScope **out_node_scope)
1293{
1294 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);
1295 if (trans_compound_stmt_inline(c, &child_scope_block->base, stmt, child_scope_block->node, out_node_scope))
1296 return nullptr;
1297 return child_scope_block->node;
1298}
1299
1300static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,
1301 const ZigClangStmtExpr *stmt, TransScope **out_node_scope)
1302{
1303 AstNode *block = trans_compound_stmt(c, scope, ZigClangStmtExpr_getSubStmt(stmt), out_node_scope);
1304 if (block == nullptr)
1305 return block;
1306 assert(block->type == NodeTypeBlock);
1307 if (block->data.block.statements.length == 0)
1308 return block;
1309
1310 Buf *label = buf_create_from_str("x");
1311 block->data.block.name = label;
1312 AstNode *return_expr = block->data.block.statements.pop();
1313 if (return_expr->type == NodeTypeBinOpExpr &&
1314 return_expr->data.bin_op_expr.bin_op == BinOpTypeAssign &&
1315 return_expr->data.bin_op_expr.op1->type == NodeTypeSymbol)
1316 {
1317 Buf *symbol_buf = return_expr->data.bin_op_expr.op1->data.symbol_expr.symbol;
1318 if (strcmp("_", buf_ptr(symbol_buf)) == 0)
1319 return_expr = return_expr->data.bin_op_expr.op2;
1320 }
1321 block->data.block.statements.append(trans_create_node_break(c, label, return_expr));
1322 return maybe_suppress_result(c, result_used, block);
1323}
1324
1325static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ZigClangReturnStmt *stmt) {
1326 const ZigClangExpr *value_expr = ZigClangReturnStmt_getRetValue(stmt);
1327 if (value_expr == nullptr) {
1328 return trans_create_node(c, NodeTypeReturnExpr);
1329 } else {
1330 AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr);
1331 return_node->data.return_expr.expr = trans_expr(c, ResultUsedYes, scope, value_expr, TransRValue);
1332 if (return_node->data.return_expr.expr == nullptr)
1333 return nullptr;
1334 return return_node;
1335 }
1336}
1337
1338static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const ZigClangIntegerLiteral *stmt) {
1339 ZigClangExprEvalResult result;
1340 if (!ZigClangIntegerLiteral_EvaluateAsInt(stmt, &result, c->ctx)) {
1341 emit_warning(c, ZigClangExpr_getBeginLoc((ZigClangExpr*)stmt), "invalid integer literal");
1342 return nullptr;
1343 }
1344 AstNode *node = trans_create_node_apint(c, ZigClangAPValue_getInt(&result.Val));
1345 return maybe_suppress_result(c, result_used, node);
1346}
1347
1348static AstNode *trans_floating_literal(Context *c, ResultUsed result_used, const ZigClangFloatingLiteral *stmt) {
1349 ZigClangAPFloat *result;
1350 if (!ZigClangExpr_EvaluateAsFloat((const ZigClangExpr *)stmt, &result, c->ctx)) {
1351 emit_warning(c, ZigClangExpr_getBeginLoc((ZigClangExpr*)stmt), "invalid floating literal");
1352 return nullptr;
1353 }
1354 AstNode *node = trans_create_node_apfloat(c, result);
1355 return maybe_suppress_result(c, result_used, node);
1356}
1357
1358static AstNode *trans_character_literal(Context *c, ResultUsed result_used, const ZigClangCharacterLiteral *stmt) {
1359 switch (ZigClangCharacterLiteral_getKind(stmt)) {
1360 case ZigClangCharacterLiteral_CharacterKind_Ascii:
1361 {
1362 unsigned val = ZigClangCharacterLiteral_getValue(stmt);
1363 // C has a somewhat obscure feature called multi-character character
1364 // constant
1365 if (val > 255)
1366 return trans_create_node_unsigned(c, val);
1367 }
1368 // fallthrough
1369 case ZigClangCharacterLiteral_CharacterKind_UTF8:
1370 {
1371 AstNode *node = trans_create_node(c, NodeTypeCharLiteral);
1372 node->data.char_literal.value = ZigClangCharacterLiteral_getValue(stmt);
1373 return maybe_suppress_result(c, result_used, node);
1374 }
1375 case ZigClangCharacterLiteral_CharacterKind_UTF16:
1376 emit_warning(c, ZigClangCharacterLiteral_getBeginLoc(stmt), "TODO support UTF16 character literals");
1377 return nullptr;
1378 case ZigClangCharacterLiteral_CharacterKind_UTF32:
1379 emit_warning(c, ZigClangCharacterLiteral_getBeginLoc(stmt), "TODO support UTF32 character literals");
1380 return nullptr;
1381 case ZigClangCharacterLiteral_CharacterKind_Wide:
1382 emit_warning(c, ZigClangCharacterLiteral_getBeginLoc(stmt), "TODO support wide character literals");
1383 return nullptr;
1384 }
1385 zig_unreachable();
1386}
1387
1388static AstNode *trans_constant_expr(Context *c, ResultUsed result_used, const ZigClangConstantExpr *expr) {
1389 const ZigClangExpr *as_expr = reinterpret_cast<const ZigClangExpr *>(expr);
1390 ZigClangExprEvalResult result;
1391 if (!ZigClangExpr_EvaluateAsConstantExpr((const ZigClangExpr *)expr, &result,
1392 ZigClangExpr_EvaluateForCodeGen, c->ctx))
1393 {
1394 emit_warning(c, ZigClangExpr_getBeginLoc(as_expr), "invalid constant expression");
1395 return nullptr;
1396 }
1397 AstNode *node = trans_ap_value(c, &result.Val, ZigClangExpr_getType(as_expr),
1398 ZigClangExpr_getBeginLoc(as_expr));
1399 return maybe_suppress_result(c, result_used, node);
1400}
1401
1402static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
1403 const ZigClangConditionalOperator *stmt)
1404{
1405 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
1406
1407 const ZigClangExpr *cond_expr = ZigClangConditionalOperator_getCond(stmt);
1408 const ZigClangExpr *true_expr = ZigClangConditionalOperator_getTrueExpr(stmt);
1409 const ZigClangExpr *false_expr = ZigClangConditionalOperator_getFalseExpr(stmt);
1410
1411 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
1412 if (node->data.if_bool_expr.condition == nullptr)
1413 return nullptr;
1414
1415 node->data.if_bool_expr.then_block = trans_expr(c, result_used, scope, true_expr, TransRValue);
1416 if (node->data.if_bool_expr.then_block == nullptr)
1417 return nullptr;
1418
1419 node->data.if_bool_expr.else_node = trans_expr(c, result_used, scope, false_expr, TransRValue);
1420 if (node->data.if_bool_expr.else_node == nullptr)
1421 return nullptr;
1422
1423 return maybe_suppress_result(c, result_used, node);
1424}
1425
1426static AstNode *trans_create_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs,
1427 BinOpType bin_op, const ZigClangExpr *rhs)
1428{
1429 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1430 node->data.bin_op_expr.bin_op = bin_op;
1431
1432 node->data.bin_op_expr.op1 = trans_expr(c, ResultUsedYes, scope, lhs, TransRValue);
1433 if (node->data.bin_op_expr.op1 == nullptr)
1434 return nullptr;
1435
1436 node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, rhs, TransRValue);
1437 if (node->data.bin_op_expr.op2 == nullptr)
1438 return nullptr;
1439
1440 return node;
1441}
1442
1443static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, const ZigClangExpr *lhs,
1444 BinOpType bin_op, const ZigClangExpr *rhs)
1445{
1446 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
1447 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1448 node->data.bin_op_expr.bin_op = bin_op;
1449
1450 node->data.bin_op_expr.op1 = trans_bool_expr(c, ResultUsedYes, scope, lhs, TransRValue);
1451 if (node->data.bin_op_expr.op1 == nullptr)
1452 return nullptr;
1453
1454 node->data.bin_op_expr.op2 = trans_bool_expr(c, ResultUsedYes, scope, rhs, TransRValue);
1455 if (node->data.bin_op_expr.op2 == nullptr)
1456 return nullptr;
1457
1458 return node;
1459}
1460
1461static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope,
1462 const ZigClangExpr *lhs, const ZigClangExpr *rhs)
1463{
1464 if (result_used == ResultUsedNo) {
1465 // common case
1466 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1467 node->data.bin_op_expr.bin_op = BinOpTypeAssign;
1468
1469 node->data.bin_op_expr.op1 = trans_expr(c, ResultUsedYes, scope, lhs, TransLValue);
1470 if (node->data.bin_op_expr.op1 == nullptr)
1471 return nullptr;
1472
1473 node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, rhs, TransRValue);
1474 if (node->data.bin_op_expr.op2 == nullptr)
1475 return nullptr;
1476
1477 return node;
1478 } else {
1479 // worst case
1480 // c: lhs = rhs
1481 // zig: (x: {
1482 // zig: const _tmp = rhs;
1483 // zig: lhs = _tmp;
1484 // zig: break :x _tmp
1485 // zig: })
1486
1487 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
1488 Buf *label_name = buf_create_from_str("x");
1489 child_scope->node->data.block.name = label_name;
1490
1491 // const _tmp = rhs;
1492 AstNode *rhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, rhs, TransRValue);
1493 if (rhs_node == nullptr) return nullptr;
1494 // TODO: avoid name collisions with generated variable names
1495 Buf* tmp_var_name = buf_create_from_str("_tmp");
1496 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node);
1497 child_scope->node->data.block.statements.append(tmp_var_decl);
1498
1499 // lhs = _tmp;
1500 AstNode *lhs_node = trans_expr(c, ResultUsedYes, &child_scope->base, lhs, TransLValue);
1501 if (lhs_node == nullptr) return nullptr;
1502 child_scope->node->data.block.statements.append(
1503 trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign,
1504 trans_create_node_symbol(c, tmp_var_name)));
1505
1506 // break :x _tmp
1507 AstNode *tmp_symbol_node = trans_create_node_symbol(c, tmp_var_name);
1508 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, tmp_symbol_node));
1509
1510 return trans_create_node_grouped_expr(c, child_scope->node);
1511 }
1512}
1513
1514static AstNode *trans_create_shift_op(Context *c, TransScope *scope, ZigClangQualType result_type,
1515 const ZigClangExpr *lhs_expr, BinOpType bin_op, const ZigClangExpr *rhs_expr)
1516{
1517 ZigClangSourceLocation rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
1518 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
1519 // lhs >> u5(rh)
1520
1521 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, lhs_expr, TransLValue);
1522 if (lhs == nullptr) return nullptr;
1523
1524 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, rhs_expr, TransRValue);
1525 if (rhs == nullptr) return nullptr;
1526 AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs);
1527
1528 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
1529}
1530
1531static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope,
1532 const ZigClangBinaryOperator *stmt)
1533{
1534 switch (ZigClangBinaryOperator_getOpcode(stmt)) {
1535 case ZigClangBO_PtrMemD:
1536 emit_warning(c, ZigClangBinaryOperator_getBeginLoc(stmt), "TODO handle more C binary operators: BO_PtrMemD");
1537 return nullptr;
1538 case ZigClangBO_PtrMemI:
1539 emit_warning(c, ZigClangBinaryOperator_getBeginLoc(stmt), "TODO handle more C binary operators: BO_PtrMemI");
1540 return nullptr;
1541 case ZigClangBO_Cmp:
1542 emit_warning(c, ZigClangBinaryOperator_getBeginLoc(stmt), "TODO handle more C binary operators: BO_Cmp");
1543 return nullptr;
1544 case ZigClangBO_Mul: {
1545 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt),
1546 qual_type_has_wrapping_overflow(c, ZigClangBinaryOperator_getType(stmt)) ? BinOpTypeMultWrap : BinOpTypeMult,
1547 ZigClangBinaryOperator_getRHS(stmt));
1548 return maybe_suppress_result(c, result_used, node);
1549 }
1550 case ZigClangBO_Div:
1551 if (qual_type_has_wrapping_overflow(c, ZigClangBinaryOperator_getType(stmt))) {
1552 // unsigned/float division uses the operator
1553 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeDiv, ZigClangBinaryOperator_getRHS(stmt));
1554 return maybe_suppress_result(c, result_used, node);
1555 } else {
1556 // signed integer division uses @divTrunc
1557 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
1558 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, ZigClangBinaryOperator_getLHS(stmt), TransLValue);
1559 if (lhs == nullptr) return nullptr;
1560 fn_call->data.fn_call_expr.params.append(lhs);
1561 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, ZigClangBinaryOperator_getRHS(stmt), TransLValue);
1562 if (rhs == nullptr) return nullptr;
1563 fn_call->data.fn_call_expr.params.append(rhs);
1564 return maybe_suppress_result(c, result_used, fn_call);
1565 }
1566 case ZigClangBO_Rem:
1567 if (qual_type_has_wrapping_overflow(c, ZigClangBinaryOperator_getType(stmt))) {
1568 // unsigned/float division uses the operator
1569 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeMod, ZigClangBinaryOperator_getRHS(stmt));
1570 return maybe_suppress_result(c, result_used, node);
1571 } else {
1572 // signed integer division uses @rem
1573 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
1574 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, ZigClangBinaryOperator_getLHS(stmt), TransLValue);
1575 if (lhs == nullptr) return nullptr;
1576 fn_call->data.fn_call_expr.params.append(lhs);
1577 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, ZigClangBinaryOperator_getRHS(stmt), TransLValue);
1578 if (rhs == nullptr) return nullptr;
1579 fn_call->data.fn_call_expr.params.append(rhs);
1580 return maybe_suppress_result(c, result_used, fn_call);
1581 }
1582 case ZigClangBO_Add: {
1583 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt),
1584 qual_type_has_wrapping_overflow(c, ZigClangBinaryOperator_getType(stmt)) ? BinOpTypeAddWrap : BinOpTypeAdd,
1585 ZigClangBinaryOperator_getRHS(stmt));
1586 return maybe_suppress_result(c, result_used, node);
1587 }
1588 case ZigClangBO_Sub: {
1589 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt),
1590 qual_type_has_wrapping_overflow(c, ZigClangBinaryOperator_getType(stmt)) ? BinOpTypeSubWrap : BinOpTypeSub,
1591 ZigClangBinaryOperator_getRHS(stmt));
1592 return maybe_suppress_result(c, result_used, node);
1593 }
1594 case ZigClangBO_Shl: {
1595 AstNode *node = trans_create_shift_op(c, scope, ZigClangBinaryOperator_getType(stmt), ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBitShiftLeft, ZigClangBinaryOperator_getRHS(stmt));
1596 return maybe_suppress_result(c, result_used, node);
1597 }
1598 case ZigClangBO_Shr: {
1599 AstNode *node = trans_create_shift_op(c, scope, ZigClangBinaryOperator_getType(stmt), ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBitShiftRight, ZigClangBinaryOperator_getRHS(stmt));
1600 return maybe_suppress_result(c, result_used, node);
1601 }
1602 case ZigClangBO_LT: {
1603 AstNode *node =trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeCmpLessThan, ZigClangBinaryOperator_getRHS(stmt));
1604 return maybe_suppress_result(c, result_used, node);
1605 }
1606 case ZigClangBO_GT: {
1607 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeCmpGreaterThan, ZigClangBinaryOperator_getRHS(stmt));
1608 return maybe_suppress_result(c, result_used, node);
1609 }
1610 case ZigClangBO_LE: {
1611 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeCmpLessOrEq, ZigClangBinaryOperator_getRHS(stmt));
1612 return maybe_suppress_result(c, result_used, node);
1613 }
1614 case ZigClangBO_GE: {
1615 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeCmpGreaterOrEq, ZigClangBinaryOperator_getRHS(stmt));
1616 return maybe_suppress_result(c, result_used, node);
1617 }
1618 case ZigClangBO_EQ: {
1619 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeCmpEq, ZigClangBinaryOperator_getRHS(stmt));
1620 return maybe_suppress_result(c, result_used, node);
1621 }
1622 case ZigClangBO_NE: {
1623 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeCmpNotEq, ZigClangBinaryOperator_getRHS(stmt));
1624 return maybe_suppress_result(c, result_used, node);
1625 }
1626 case ZigClangBO_And: {
1627 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBinAnd, ZigClangBinaryOperator_getRHS(stmt));
1628 return maybe_suppress_result(c, result_used, node);
1629 }
1630 case ZigClangBO_Xor: {
1631 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBinXor, ZigClangBinaryOperator_getRHS(stmt));
1632 return maybe_suppress_result(c, result_used, node);
1633 }
1634 case ZigClangBO_Or: {
1635 AstNode *node = trans_create_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBinOr, ZigClangBinaryOperator_getRHS(stmt));
1636 return maybe_suppress_result(c, result_used, node);
1637 }
1638 case ZigClangBO_LAnd: {
1639 AstNode *node = trans_create_bool_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBoolAnd, ZigClangBinaryOperator_getRHS(stmt));
1640 return maybe_suppress_result(c, result_used, node);
1641 }
1642 case ZigClangBO_LOr: {
1643 AstNode *node = trans_create_bool_bin_op(c, scope, ZigClangBinaryOperator_getLHS(stmt), BinOpTypeBoolOr, ZigClangBinaryOperator_getRHS(stmt));
1644 return maybe_suppress_result(c, result_used, node);
1645 }
1646 case ZigClangBO_Assign:
1647 return trans_create_assign(c, result_used, scope, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt));
1648 case ZigClangBO_Comma:
1649 {
1650 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
1651 Buf *label_name = buf_create_from_str("x");
1652 scope_block->node->data.block.name = label_name;
1653
1654 AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, ZigClangBinaryOperator_getLHS(stmt), TransRValue);
1655 if (lhs == nullptr)
1656 return nullptr;
1657 scope_block->node->data.block.statements.append(lhs);
1658
1659 AstNode *rhs = trans_expr(c, ResultUsedYes, &scope_block->base, ZigClangBinaryOperator_getRHS(stmt), TransRValue);
1660 if (rhs == nullptr)
1661 return nullptr;
1662
1663 rhs = trans_create_node_break(c, label_name, rhs);
1664 scope_block->node->data.block.statements.append(rhs);
1665 return maybe_suppress_result(c, result_used, scope_block->node);
1666 }
1667 case ZigClangBO_MulAssign:
1668 case ZigClangBO_DivAssign:
1669 case ZigClangBO_RemAssign:
1670 case ZigClangBO_AddAssign:
1671 case ZigClangBO_SubAssign:
1672 case ZigClangBO_ShlAssign:
1673 case ZigClangBO_ShrAssign:
1674 case ZigClangBO_AndAssign:
1675 case ZigClangBO_XorAssign:
1676 case ZigClangBO_OrAssign:
1677 zig_unreachable();
1678 }
1679
1680 zig_unreachable();
1681}
1682
1683static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,
1684 const ZigClangCompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
1685{
1686 ZigClangSourceLocation rhs_location = ZigClangExpr_getBeginLoc(ZigClangCompoundAssignOperator_getRHS(stmt));
1687 ZigClangQualType computation_lhs_type = ZigClangCompoundAssignOperator_getComputationLHSType(stmt);
1688 AstNode *rhs_type = qual_type_to_log2_int_ref(c, computation_lhs_type, rhs_location);
1689 ZigClangQualType computation_result_type = ZigClangCompoundAssignOperator_getComputationResultType(stmt);
1690
1691 bool use_intermediate_casts = ZigClangQualType_getTypePtr(computation_lhs_type) !=
1692 ZigClangQualType_getTypePtr(computation_result_type);
1693 if (!use_intermediate_casts && result_used == ResultUsedNo) {
1694 // simple common case, where the C and Zig are identical:
1695 // lhs >>= rhs
1696 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, ZigClangCompoundAssignOperator_getLHS(stmt), TransLValue);
1697 if (lhs == nullptr) return nullptr;
1698
1699 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue);
1700 if (rhs == nullptr) return nullptr;
1701 AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs);
1702
1703 return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs);
1704 } else {
1705 // need more complexity. worst case, this looks like this:
1706 // c: lhs >>= rhs
1707 // zig: (x: {
1708 // zig: const _ref = &lhs;
1709 // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1710 // zig: break :x *_ref
1711 // zig: })
1712 // where u5 is the appropriate type
1713
1714 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
1715 Buf *label_name = buf_create_from_str("x");
1716 child_scope->node->data.block.name = label_name;
1717
1718 // const _ref = &lhs;
1719 AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base,
1720 ZigClangCompoundAssignOperator_getLHS(stmt), TransLValue);
1721 if (lhs == nullptr) return nullptr;
1722 AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
1723 // TODO: avoid name collisions with generated variable names
1724 Buf* tmp_var_name = buf_create_from_str("_ref");
1725 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1726 child_scope->node->data.block.statements.append(tmp_var_decl);
1727
1728 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1729
1730 AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue);
1731 if (rhs == nullptr) return nullptr;
1732 AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs);
1733
1734 // operation_type(*_ref)
1735 AstNode *operation_type_cast = trans_c_cast(c, rhs_location,
1736 computation_lhs_type,
1737 ZigClangExpr_getType(ZigClangCompoundAssignOperator_getLHS(stmt)),
1738 trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)));
1739
1740 // result_type(... >> u5(rhs))
1741 AstNode *result_type_cast = trans_c_cast(c, rhs_location,
1742 computation_result_type,
1743 computation_lhs_type,
1744 trans_create_node_bin_op(c,
1745 operation_type_cast,
1746 bin_op,
1747 coerced_rhs));
1748
1749 // *_ref = ...
1750 AstNode *assign_statement = trans_create_node_bin_op(c,
1751 trans_create_node_ptr_deref(c,
1752 trans_create_node_symbol(c, tmp_var_name)),
1753 BinOpTypeAssign, result_type_cast);
1754
1755 child_scope->node->data.block.statements.append(assign_statement);
1756
1757 if (result_used == ResultUsedYes) {
1758 // break :x *_ref
1759 child_scope->node->data.block.statements.append(
1760 trans_create_node_break(c, label_name,
1761 trans_create_node_ptr_deref(c,
1762 trans_create_node_symbol(c, tmp_var_name))));
1763 }
1764
1765 return trans_create_node_grouped_expr(c, child_scope->node);
1766 }
1767}
1768
1769static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope,
1770 const ZigClangCompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
1771{
1772 if (result_used == ResultUsedNo) {
1773 // simple common case, where the C and Zig are identical:
1774 // lhs += rhs
1775 AstNode *lhs = trans_expr(c, ResultUsedYes, scope, ZigClangCompoundAssignOperator_getLHS(stmt), TransLValue);
1776 if (lhs == nullptr) return nullptr;
1777 AstNode *rhs = trans_expr(c, ResultUsedYes, scope, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue);
1778 if (rhs == nullptr) return nullptr;
1779 return trans_create_node_bin_op(c, lhs, assign_op, rhs);
1780 } else {
1781 // need more complexity. worst case, this looks like this:
1782 // c: lhs += rhs
1783 // zig: (x: {
1784 // zig: const _ref = &lhs;
1785 // zig: *_ref = *_ref + rhs;
1786 // zig: break :x *_ref
1787 // zig: })
1788
1789 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
1790 Buf *label_name = buf_create_from_str("x");
1791 child_scope->node->data.block.name = label_name;
1792
1793 // const _ref = &lhs;
1794 AstNode *lhs = trans_expr(c, ResultUsedYes, &child_scope->base,
1795 ZigClangCompoundAssignOperator_getLHS(stmt), TransLValue);
1796 if (lhs == nullptr) return nullptr;
1797 AstNode *addr_of_lhs = trans_create_node_addr_of(c, lhs);
1798 // TODO: avoid name collisions with generated variable names
1799 Buf* tmp_var_name = buf_create_from_str("_ref");
1800 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1801 child_scope->node->data.block.statements.append(tmp_var_decl);
1802
1803 // *_ref = *_ref + rhs;
1804
1805 AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base,
1806 ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue);
1807 if (rhs == nullptr) return nullptr;
1808
1809 AstNode *assign_statement = trans_create_node_bin_op(c,
1810 trans_create_node_ptr_deref(c,
1811 trans_create_node_symbol(c, tmp_var_name)),
1812 BinOpTypeAssign,
1813 trans_create_node_bin_op(c,
1814 trans_create_node_ptr_deref(c,
1815 trans_create_node_symbol(c, tmp_var_name)),
1816 bin_op,
1817 rhs));
1818 child_scope->node->data.block.statements.append(assign_statement);
1819
1820 // break :x *_ref
1821 child_scope->node->data.block.statements.append(
1822 trans_create_node_break(c, label_name,
1823 trans_create_node_ptr_deref(c,
1824 trans_create_node_symbol(c, tmp_var_name))));
1825
1826 return trans_create_node_grouped_expr(c, child_scope->node);
1827 }
1828}
1829
1830
1831static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
1832 const ZigClangCompoundAssignOperator *stmt)
1833{
1834 switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
1835 case ZigClangBO_MulAssign:
1836 if (qual_type_has_wrapping_overflow(c, ZigClangCompoundAssignOperator_getType(stmt)))
1837 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
1838 else
1839 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1840 case ZigClangBO_DivAssign:
1841 emit_warning(c, ZigClangCompoundAssignOperator_getBeginLoc(stmt), "TODO handle more C compound assign operators: BO_DivAssign");
1842 return nullptr;
1843 case ZigClangBO_RemAssign:
1844 emit_warning(c, ZigClangCompoundAssignOperator_getBeginLoc(stmt), "TODO handle more C compound assign operators: BO_RemAssign");
1845 return nullptr;
1846 case ZigClangBO_Cmp:
1847 emit_warning(c, ZigClangCompoundAssignOperator_getBeginLoc(stmt), "TODO handle more C compound assign operators: BO_Cmp");
1848 return nullptr;
1849 case ZigClangBO_AddAssign:
1850 if (qual_type_has_wrapping_overflow(c, ZigClangCompoundAssignOperator_getType(stmt)))
1851 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
1852 else
1853 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1854 case ZigClangBO_SubAssign:
1855 if (qual_type_has_wrapping_overflow(c, ZigClangCompoundAssignOperator_getType(stmt)))
1856 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
1857 else
1858 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1859 case ZigClangBO_ShlAssign:
1860 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1861 case ZigClangBO_ShrAssign:
1862 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1863 case ZigClangBO_AndAssign:
1864 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1865 case ZigClangBO_XorAssign:
1866 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1867 case ZigClangBO_OrAssign:
1868 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1869 case ZigClangBO_PtrMemD:
1870 case ZigClangBO_PtrMemI:
1871 case ZigClangBO_Assign:
1872 case ZigClangBO_Mul:
1873 case ZigClangBO_Div:
1874 case ZigClangBO_Rem:
1875 case ZigClangBO_Add:
1876 case ZigClangBO_Sub:
1877 case ZigClangBO_Shl:
1878 case ZigClangBO_Shr:
1879 case ZigClangBO_LT:
1880 case ZigClangBO_GT:
1881 case ZigClangBO_LE:
1882 case ZigClangBO_GE:
1883 case ZigClangBO_EQ:
1884 case ZigClangBO_NE:
1885 case ZigClangBO_And:
1886 case ZigClangBO_Xor:
1887 case ZigClangBO_Or:
1888 case ZigClangBO_LAnd:
1889 case ZigClangBO_LOr:
1890 case ZigClangBO_Comma:
1891 zig_unreachable();
1892 }
1893
1894 zig_unreachable();
1895}
1896
1897static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
1898 const ZigClangImplicitCastExpr *stmt)
1899{
1900 switch (ZigClangImplicitCastExpr_getCastKind(stmt)) {
1901 case ZigClangCK_LValueToRValue:
1902 return trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
1903 case ZigClangCK_IntegralCast:
1904 {
1905 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
1906 if (target_node == nullptr)
1907 return nullptr;
1908 AstNode *node = trans_c_cast(c, ZigClangImplicitCastExpr_getBeginLoc(stmt),
1909 ZigClangExpr_getType(reinterpret_cast<const ZigClangExpr *>(stmt)),
1910 ZigClangExpr_getType(ZigClangImplicitCastExpr_getSubExpr(stmt)),
1911 target_node);
1912 return maybe_suppress_result(c, result_used, node);
1913 }
1914 case ZigClangCK_FunctionToPointerDecay:
1915 case ZigClangCK_ArrayToPointerDecay:
1916 {
1917 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
1918 if (target_node == nullptr)
1919 return nullptr;
1920 return maybe_suppress_result(c, result_used, target_node);
1921 }
1922 case ZigClangCK_BitCast:
1923 {
1924 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
1925 if (target_node == nullptr)
1926 return nullptr;
1927
1928 const ZigClangQualType dest_type = get_expr_qual_type(c, reinterpret_cast<const ZigClangExpr *>(stmt));
1929 const ZigClangQualType src_type = get_expr_qual_type(c, ZigClangImplicitCastExpr_getSubExpr(stmt));
1930
1931 return trans_c_cast(c, ZigClangImplicitCastExpr_getBeginLoc(stmt),
1932 dest_type, src_type, target_node);
1933 }
1934 case ZigClangCK_NullToPointer:
1935 return trans_create_node(c, NodeTypeNullLiteral);
1936 case ZigClangCK_NoOp:
1937 return trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
1938 case ZigClangCK_Dependent:
1939 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_Dependent");
1940 return nullptr;
1941 case ZigClangCK_LValueBitCast:
1942 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_LValueBitCast");
1943 return nullptr;
1944 case ZigClangCK_BaseToDerived:
1945 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_BaseToDerived");
1946 return nullptr;
1947 case ZigClangCK_DerivedToBase:
1948 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_DerivedToBase");
1949 return nullptr;
1950 case ZigClangCK_UncheckedDerivedToBase:
1951 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1952 return nullptr;
1953 case ZigClangCK_Dynamic:
1954 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_Dynamic");
1955 return nullptr;
1956 case ZigClangCK_ToUnion:
1957 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_ToUnion");
1958 return nullptr;
1959 case ZigClangCK_NullToMemberPointer:
1960 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_NullToMemberPointer");
1961 return nullptr;
1962 case ZigClangCK_BaseToDerivedMemberPointer:
1963 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
1964 return nullptr;
1965 case ZigClangCK_DerivedToBaseMemberPointer:
1966 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
1967 return nullptr;
1968 case ZigClangCK_MemberPointerToBoolean:
1969 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_MemberPointerToBoolean");
1970 return nullptr;
1971 case ZigClangCK_ReinterpretMemberPointer:
1972 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_ReinterpretMemberPointer");
1973 return nullptr;
1974 case ZigClangCK_UserDefinedConversion:
1975 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C translation cast CK_UserDefinedConversion");
1976 return nullptr;
1977 case ZigClangCK_ConstructorConversion:
1978 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ConstructorConversion");
1979 return nullptr;
1980 case ZigClangCK_PointerToBoolean:
1981 {
1982 const ZigClangExpr *expr = ZigClangImplicitCastExpr_getSubExpr(stmt);
1983 AstNode *val = trans_expr(c, ResultUsedYes, scope, expr, TransRValue);
1984 if (val == nullptr)
1985 return nullptr;
1986
1987 AstNode *val_ptr = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
1988 val_ptr->data.fn_call_expr.params.append(val);
1989
1990 AstNode *zero = trans_create_node_unsigned(c, 0);
1991
1992 // Translate as @ptrToInt((&val) != 0)
1993 return trans_create_node_bin_op(c, val_ptr, BinOpTypeCmpNotEq, zero);
1994 }
1995 case ZigClangCK_ToVoid:
1996 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ToVoid");
1997 return nullptr;
1998 case ZigClangCK_VectorSplat:
1999 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_VectorSplat");
2000 return nullptr;
2001 case ZigClangCK_IntegralToBoolean:
2002 {
2003 const ZigClangExpr *expr = ZigClangImplicitCastExpr_getSubExpr(stmt);
2004
2005 bool expr_val;
2006 if (ZigClangExpr_EvaluateAsBooleanCondition(expr, &expr_val, c->ctx, false)) {
2007 return trans_create_node_bool(c, expr_val);
2008 }
2009
2010 AstNode *val = trans_expr(c, ResultUsedYes, scope, expr, TransRValue);
2011 if (val == nullptr)
2012 return nullptr;
2013
2014 AstNode *zero = trans_create_node_unsigned(c, 0);
2015
2016 // Translate as val != 0
2017 return trans_create_node_bin_op(c, val, BinOpTypeCmpNotEq, zero);
2018 }
2019 case ZigClangCK_PointerToIntegral:
2020 {
2021 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
2022 if (target_node == nullptr)
2023 return nullptr;
2024
2025 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2026 if (dest_type_node == nullptr)
2027 return nullptr;
2028
2029 AstNode *val_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt");
2030 val_node->data.fn_call_expr.params.append(target_node);
2031 // @ptrToInt always returns a usize
2032 AstNode *node = trans_create_node_builtin_fn_call_str(c, "intCast");
2033 node->data.fn_call_expr.params.append(dest_type_node);
2034 node->data.fn_call_expr.params.append(val_node);
2035
2036 return maybe_suppress_result(c, result_used, node);
2037 }
2038 case ZigClangCK_IntegralToPointer:
2039 {
2040 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
2041 if (target_node == nullptr)
2042 return nullptr;
2043
2044 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2045 if (dest_type_node == nullptr)
2046 return nullptr;
2047
2048 AstNode *node = trans_create_node_builtin_fn_call_str(c, "intToPtr");
2049 node->data.fn_call_expr.params.append(dest_type_node);
2050 node->data.fn_call_expr.params.append(target_node);
2051
2052 return maybe_suppress_result(c, result_used, node);
2053 }
2054 case ZigClangCK_IntegralToFloating:
2055 case ZigClangCK_FloatingToIntegral:
2056 {
2057 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, ZigClangImplicitCastExpr_getSubExpr(stmt), TransRValue);
2058 if (target_node == nullptr)
2059 return nullptr;
2060
2061 AstNode *dest_type_node = get_expr_type(c, (const ZigClangExpr *)stmt);
2062 if (dest_type_node == nullptr)
2063 return nullptr;
2064
2065 char const *fn = (ZigClangImplicitCastExpr_getCastKind(stmt) == ZigClangCK_IntegralToFloating) ?
2066 "intToFloat" : "floatToInt";
2067 AstNode *node = trans_create_node_builtin_fn_call_str(c, fn);
2068 node->data.fn_call_expr.params.append(dest_type_node);
2069 node->data.fn_call_expr.params.append(target_node);
2070
2071 return maybe_suppress_result(c, result_used, node);
2072 }
2073 case ZigClangCK_FixedPointCast:
2074 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FixedPointCast");
2075 return nullptr;
2076 case ZigClangCK_FixedPointToBoolean:
2077 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FixedPointToBoolean");
2078 return nullptr;
2079 case ZigClangCK_FloatingToBoolean:
2080 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingToBoolean");
2081 return nullptr;
2082 case ZigClangCK_BooleanToSignedIntegral:
2083 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_BooleanToSignedIntegral");
2084 return nullptr;
2085 case ZigClangCK_FloatingCast:
2086 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingCast");
2087 return nullptr;
2088 case ZigClangCK_CPointerToObjCPointerCast:
2089 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_CPointerToObjCPointerCast");
2090 return nullptr;
2091 case ZigClangCK_BlockPointerToObjCPointerCast:
2092 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_BlockPointerToObjCPointerCast");
2093 return nullptr;
2094 case ZigClangCK_AnyPointerToBlockPointerCast:
2095 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_AnyPointerToBlockPointerCast");
2096 return nullptr;
2097 case ZigClangCK_ObjCObjectLValueCast:
2098 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ObjCObjectLValueCast");
2099 return nullptr;
2100 case ZigClangCK_FloatingRealToComplex:
2101 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingRealToComplex");
2102 return nullptr;
2103 case ZigClangCK_FloatingComplexToReal:
2104 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingComplexToReal");
2105 return nullptr;
2106 case ZigClangCK_FloatingComplexToBoolean:
2107 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingComplexToBoolean");
2108 return nullptr;
2109 case ZigClangCK_FloatingComplexCast:
2110 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingComplexCast");
2111 return nullptr;
2112 case ZigClangCK_FloatingComplexToIntegralComplex:
2113 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FloatingComplexToIntegralComplex");
2114 return nullptr;
2115 case ZigClangCK_IntegralRealToComplex:
2116 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntegralRealToComplex");
2117 return nullptr;
2118 case ZigClangCK_IntegralComplexToReal:
2119 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntegralComplexToReal");
2120 return nullptr;
2121 case ZigClangCK_IntegralComplexToBoolean:
2122 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntegralComplexToBoolean");
2123 return nullptr;
2124 case ZigClangCK_IntegralComplexCast:
2125 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntegralComplexCast");
2126 return nullptr;
2127 case ZigClangCK_IntegralComplexToFloatingComplex:
2128 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntegralComplexToFloatingComplex");
2129 return nullptr;
2130 case ZigClangCK_ARCProduceObject:
2131 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ARCProduceObject");
2132 return nullptr;
2133 case ZigClangCK_ARCConsumeObject:
2134 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ARCConsumeObject");
2135 return nullptr;
2136 case ZigClangCK_ARCReclaimReturnedObject:
2137 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ARCReclaimReturnedObject");
2138 return nullptr;
2139 case ZigClangCK_ARCExtendBlockObject:
2140 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ARCExtendBlockObject");
2141 return nullptr;
2142 case ZigClangCK_AtomicToNonAtomic:
2143 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_AtomicToNonAtomic");
2144 return nullptr;
2145 case ZigClangCK_NonAtomicToAtomic:
2146 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_NonAtomicToAtomic");
2147 return nullptr;
2148 case ZigClangCK_CopyAndAutoreleaseBlockObject:
2149 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_CopyAndAutoreleaseBlockObject");
2150 return nullptr;
2151 case ZigClangCK_BuiltinFnToFnPtr:
2152 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_BuiltinFnToFnPtr");
2153 return nullptr;
2154 case ZigClangCK_ZeroToOCLOpaqueType:
2155 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_ZeroToOCLOpaqueType");
2156 return nullptr;
2157 case ZigClangCK_AddressSpaceConversion:
2158 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_AddressSpaceConversion");
2159 return nullptr;
2160 case ZigClangCK_IntToOCLSampler:
2161 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntToOCLSampler");
2162 return nullptr;
2163 case ZigClangCK_LValueToRValueBitCast:
2164 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_LValueToRValueBitCast");
2165 return nullptr;
2166 case ZigClangCK_FixedPointToIntegral:
2167 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_FixedPointToIntegral");
2168 return nullptr;
2169 case ZigClangCK_IntegralToFixedPoint:
2170 emit_warning(c, ZigClangImplicitCastExpr_getBeginLoc(stmt), "TODO handle C CK_IntegralToFixedPointral");
2171 return nullptr;
2172 }
2173 zig_unreachable();
2174}
2175
2176static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const ZigClangDeclRefExpr *stmt, TransLRValue lrval) {
2177 const ZigClangValueDecl *value_decl = ZigClangDeclRefExpr_getDecl(stmt);
2178 Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)value_decl));
2179 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
2180 if (lrval == TransLValue) {
2181 c->ptr_params.put(zig_symbol_name, true);
2182 }
2183 return trans_create_node_symbol(c, zig_symbol_name);
2184}
2185
2186static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,
2187 const ZigClangUnaryOperator *stmt, BinOpType assign_op)
2188{
2189 const ZigClangExpr *op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
2190
2191 if (result_used == ResultUsedNo) {
2192 // common case
2193 // c: expr++
2194 // zig: expr += 1
2195 return trans_create_node_bin_op(c,
2196 trans_expr(c, ResultUsedYes, scope, op_expr, TransLValue),
2197 assign_op,
2198 trans_create_node_unsigned(c, 1));
2199 }
2200 // worst case
2201 // c: expr++
2202 // zig: (x: {
2203 // zig: const _ref = &expr;
2204 // zig: const _tmp = *_ref;
2205 // zig: *_ref += 1;
2206 // zig: break :x _tmp
2207 // zig: })
2208 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
2209 Buf *label_name = buf_create_from_str("x");
2210 child_scope->node->data.block.name = label_name;
2211
2212 // const _ref = &expr;
2213 AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue);
2214 if (expr == nullptr) return nullptr;
2215 AstNode *addr_of_expr = trans_create_node_addr_of(c, expr);
2216 // TODO: avoid name collisions with generated variable names
2217 Buf* ref_var_name = buf_create_from_str("_ref");
2218 AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr);
2219 child_scope->node->data.block.statements.append(ref_var_decl);
2220
2221 // const _tmp = *_ref;
2222 Buf* tmp_var_name = buf_create_from_str("_tmp");
2223 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr,
2224 trans_create_node_ptr_deref(c,
2225 trans_create_node_symbol(c, ref_var_name)));
2226 child_scope->node->data.block.statements.append(tmp_var_decl);
2227
2228 // *_ref += 1;
2229 AstNode *assign_statement = trans_create_node_bin_op(c,
2230 trans_create_node_ptr_deref(c,
2231 trans_create_node_symbol(c, ref_var_name)),
2232 assign_op,
2233 trans_create_node_unsigned(c, 1));
2234 child_scope->node->data.block.statements.append(assign_statement);
2235
2236 // break :x _tmp
2237 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, trans_create_node_symbol(c, tmp_var_name)));
2238
2239 return trans_create_node_grouped_expr(c, child_scope->node);
2240}
2241
2242static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,
2243 const ZigClangUnaryOperator *stmt, BinOpType assign_op)
2244{
2245 const ZigClangExpr *op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
2246
2247 if (result_used == ResultUsedNo) {
2248 // common case
2249 // c: ++expr
2250 // zig: expr += 1
2251 return trans_create_node_bin_op(c,
2252 trans_expr(c, ResultUsedYes, scope, op_expr, TransLValue),
2253 assign_op,
2254 trans_create_node_unsigned(c, 1));
2255 }
2256 // worst case
2257 // c: ++expr
2258 // zig: (x: {
2259 // zig: const _ref = &expr;
2260 // zig: *_ref += 1;
2261 // zig: break :x *_ref
2262 // zig: })
2263 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
2264 Buf *label_name = buf_create_from_str("x");
2265 child_scope->node->data.block.name = label_name;
2266
2267 // const _ref = &expr;
2268 AstNode *expr = trans_expr(c, ResultUsedYes, &child_scope->base, op_expr, TransLValue);
2269 if (expr == nullptr) return nullptr;
2270 AstNode *addr_of_expr = trans_create_node_addr_of(c, expr);
2271 // TODO: avoid name collisions with generated variable names
2272 Buf* ref_var_name = buf_create_from_str("_ref");
2273 AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr);
2274 child_scope->node->data.block.statements.append(ref_var_decl);
2275
2276 // *_ref += 1;
2277 AstNode *assign_statement = trans_create_node_bin_op(c,
2278 trans_create_node_ptr_deref(c,
2279 trans_create_node_symbol(c, ref_var_name)),
2280 assign_op,
2281 trans_create_node_unsigned(c, 1));
2282 child_scope->node->data.block.statements.append(assign_statement);
2283
2284 // break :x *_ref
2285 AstNode *deref_expr = trans_create_node_ptr_deref(c,
2286 trans_create_node_symbol(c, ref_var_name));
2287 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, deref_expr));
2288
2289 return trans_create_node_grouped_expr(c, child_scope->node);
2290}
2291
2292static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope,
2293 const ZigClangUnaryOperator *stmt)
2294{
2295 switch (ZigClangUnaryOperator_getOpcode(stmt)) {
2296 case ZigClangUO_PostInc:
2297 if (qual_type_has_wrapping_overflow(c, ZigClangUnaryOperator_getType(stmt)))
2298 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
2299 else
2300 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2301 case ZigClangUO_PostDec:
2302 if (qual_type_has_wrapping_overflow(c, ZigClangUnaryOperator_getType(stmt)))
2303 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
2304 else
2305 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2306 case ZigClangUO_PreInc:
2307 if (qual_type_has_wrapping_overflow(c, ZigClangUnaryOperator_getType(stmt)))
2308 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
2309 else
2310 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
2311 case ZigClangUO_PreDec:
2312 if (qual_type_has_wrapping_overflow(c, ZigClangUnaryOperator_getType(stmt)))
2313 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
2314 else
2315 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
2316 case ZigClangUO_AddrOf:
2317 {
2318 AstNode *value_node = trans_expr(c, result_used, scope, ZigClangUnaryOperator_getSubExpr(stmt), TransLValue);
2319 if (value_node == nullptr)
2320 return value_node;
2321 return trans_create_node_addr_of(c, value_node);
2322 }
2323 case ZigClangUO_Deref:
2324 {
2325 AstNode *value_node = trans_expr(c, result_used, scope, ZigClangUnaryOperator_getSubExpr(stmt), TransRValue);
2326 if (value_node == nullptr)
2327 return nullptr;
2328 bool is_fn_ptr = qual_type_is_fn_ptr(ZigClangExpr_getType(ZigClangUnaryOperator_getSubExpr(stmt)));
2329 if (is_fn_ptr)
2330 return value_node;
2331 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
2332 return trans_create_node_ptr_deref(c, unwrapped);
2333 }
2334 case ZigClangUO_Plus:
2335 emit_warning(c, ZigClangUnaryOperator_getBeginLoc(stmt), "TODO handle C translation UO_Plus");
2336 return nullptr;
2337 case ZigClangUO_Minus:
2338 {
2339 const ZigClangExpr *op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
2340 if (!qual_type_has_wrapping_overflow(c, ZigClangExpr_getType(op_expr))) {
2341 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
2342 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
2343
2344 node->data.prefix_op_expr.primary_expr = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2345 if (node->data.prefix_op_expr.primary_expr == nullptr)
2346 return nullptr;
2347
2348 return node;
2349 } else if (c_is_unsigned_integer(c, ZigClangExpr_getType(op_expr))) {
2350 // we gotta emit 0 -% x
2351 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
2352 node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);
2353
2354 node->data.bin_op_expr.op2 = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2355 if (node->data.bin_op_expr.op2 == nullptr)
2356 return nullptr;
2357
2358 node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;
2359 return node;
2360 } else {
2361 emit_warning(c, ZigClangUnaryOperator_getBeginLoc(stmt), "C negation with non float non integer");
2362 return nullptr;
2363 }
2364 }
2365 case ZigClangUO_Not:
2366 {
2367 const ZigClangExpr *op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
2368 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2369 if (sub_node == nullptr)
2370 return nullptr;
2371
2372 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
2373 }
2374 case ZigClangUO_LNot:
2375 {
2376 const ZigClangExpr *op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
2377 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2378 if (sub_node == nullptr)
2379 return nullptr;
2380
2381 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
2382 }
2383 case ZigClangUO_Real:
2384 emit_warning(c, ZigClangUnaryOperator_getBeginLoc(stmt), "TODO handle C translation UO_Real");
2385 return nullptr;
2386 case ZigClangUO_Imag:
2387 emit_warning(c, ZigClangUnaryOperator_getBeginLoc(stmt), "TODO handle C translation UO_Imag");
2388 return nullptr;
2389 case ZigClangUO_Extension:
2390 return trans_expr(c, result_used, scope, ZigClangUnaryOperator_getSubExpr(stmt), TransLValue);
2391 case ZigClangUO_Coawait:
2392 emit_warning(c, ZigClangUnaryOperator_getBeginLoc(stmt), "TODO handle C translation UO_Coawait");
2393 return nullptr;
2394 }
2395 zig_unreachable();
2396}
2397
2398static int trans_local_declaration(Context *c, TransScope *scope, const ZigClangDeclStmt *stmt,
2399 AstNode **out_node, TransScope **out_scope)
2400{
2401 // declarations are added via the scope
2402 *out_node = nullptr;
2403
2404 TransScopeBlock *scope_block = trans_scope_block_find(scope);
2405 assert(scope_block != nullptr);
2406
2407 for (ZigClangDeclStmt_const_decl_iterator iter = ZigClangDeclStmt_decl_begin(stmt),
2408 iter_end = ZigClangDeclStmt_decl_end(stmt);
2409 iter != iter_end; ++iter)
2410 {
2411 ZigClangDecl *decl = *iter;
2412 switch (ZigClangDecl_getKind(decl)) {
2413 case ZigClangDeclVar: {
2414 ZigClangVarDecl *var_decl = (ZigClangVarDecl *)decl;
2415 ZigClangQualType qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
2416 AstNode *init_node = nullptr;
2417 if (ZigClangVarDecl_hasInit(var_decl)) {
2418 init_node = trans_expr(c, ResultUsedYes, scope, ZigClangVarDecl_getInit(var_decl), TransRValue);
2419 if (init_node == nullptr)
2420 return ErrorUnexpected;
2421
2422 } else {
2423 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
2424 }
2425 AstNode *type_node = trans_qual_type(c, qual_type, ZigClangDeclStmt_getBeginLoc(stmt));
2426 if (type_node == nullptr)
2427 return ErrorUnexpected;
2428
2429 Buf *c_symbol_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl));
2430
2431 TransScopeVar *var_scope = trans_scope_var_create(c, scope, c_symbol_name);
2432 scope = &var_scope->base;
2433
2434 AstNode *node = trans_create_node_var_decl_local(c,
2435 ZigClangQualType_isConstQualified(qual_type),
2436 var_scope->zig_name, type_node, init_node);
2437
2438 scope_block->node->data.block.statements.append(node);
2439 continue;
2440 }
2441 case ZigClangDeclAccessSpec:
2442 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle decl kind AccessSpec");
2443 return ErrorUnexpected;
2444 case ZigClangDeclBlock:
2445 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Block");
2446 return ErrorUnexpected;
2447 case ZigClangDeclCaptured:
2448 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Captured");
2449 return ErrorUnexpected;
2450 case ZigClangDeclClassScopeFunctionSpecialization:
2451 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ClassScopeFunctionSpecialization");
2452 return ErrorUnexpected;
2453 case ZigClangDeclEmpty:
2454 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Empty");
2455 return ErrorUnexpected;
2456 case ZigClangDeclExport:
2457 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Export");
2458 return ErrorUnexpected;
2459 case ZigClangDeclExternCContext:
2460 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ExternCContext");
2461 return ErrorUnexpected;
2462 case ZigClangDeclFileScopeAsm:
2463 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C FileScopeAsm");
2464 return ErrorUnexpected;
2465 case ZigClangDeclFriend:
2466 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Friend");
2467 return ErrorUnexpected;
2468 case ZigClangDeclFriendTemplate:
2469 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C FriendTemplate");
2470 return ErrorUnexpected;
2471 case ZigClangDeclImport:
2472 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Import");
2473 return ErrorUnexpected;
2474 case ZigClangDeclLinkageSpec:
2475 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C LinkageSpec");
2476 return ErrorUnexpected;
2477 case ZigClangDeclLabel:
2478 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Label");
2479 return ErrorUnexpected;
2480 case ZigClangDeclNamespace:
2481 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Namespace");
2482 return ErrorUnexpected;
2483 case ZigClangDeclNamespaceAlias:
2484 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C NamespaceAlias");
2485 return ErrorUnexpected;
2486 case ZigClangDeclObjCCompatibleAlias:
2487 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCCompatibleAlias");
2488 return ErrorUnexpected;
2489 case ZigClangDeclObjCCategory:
2490 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCCategory");
2491 return ErrorUnexpected;
2492 case ZigClangDeclObjCCategoryImpl:
2493 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCCategoryImpl");
2494 return ErrorUnexpected;
2495 case ZigClangDeclObjCImplementation:
2496 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCImplementation");
2497 return ErrorUnexpected;
2498 case ZigClangDeclObjCInterface:
2499 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCInterface");
2500 return ErrorUnexpected;
2501 case ZigClangDeclObjCProtocol:
2502 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCProtocol");
2503 return ErrorUnexpected;
2504 case ZigClangDeclObjCMethod:
2505 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCMethod");
2506 return ErrorUnexpected;
2507 case ZigClangDeclObjCProperty:
2508 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCProperty");
2509 return ErrorUnexpected;
2510 case ZigClangDeclBuiltinTemplate:
2511 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C BuiltinTemplate");
2512 return ErrorUnexpected;
2513 case ZigClangDeclClassTemplate:
2514 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ClassTemplate");
2515 return ErrorUnexpected;
2516 case ZigClangDeclFunctionTemplate:
2517 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C FunctionTemplate");
2518 return ErrorUnexpected;
2519 case ZigClangDeclTypeAliasTemplate:
2520 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C TypeAliasTemplate");
2521 return ErrorUnexpected;
2522 case ZigClangDeclVarTemplate:
2523 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C VarTemplate");
2524 return ErrorUnexpected;
2525 case ZigClangDeclTemplateTemplateParm:
2526 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C TemplateTemplateParm");
2527 return ErrorUnexpected;
2528 case ZigClangDeclEnum:
2529 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Enum");
2530 return ErrorUnexpected;
2531 case ZigClangDeclRecord:
2532 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Record");
2533 return ErrorUnexpected;
2534 case ZigClangDeclCXXRecord:
2535 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C CXXRecord");
2536 return ErrorUnexpected;
2537 case ZigClangDeclClassTemplateSpecialization:
2538 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ClassTemplateSpecialization");
2539 return ErrorUnexpected;
2540 case ZigClangDeclClassTemplatePartialSpecialization:
2541 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ClassTemplatePartialSpecialization");
2542 return ErrorUnexpected;
2543 case ZigClangDeclTemplateTypeParm:
2544 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C TemplateTypeParm");
2545 return ErrorUnexpected;
2546 case ZigClangDeclObjCTypeParam:
2547 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCTypeParam");
2548 return ErrorUnexpected;
2549 case ZigClangDeclTypeAlias:
2550 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C TypeAlias");
2551 return ErrorUnexpected;
2552 case ZigClangDeclTypedef:
2553 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Typedef");
2554 return ErrorUnexpected;
2555 case ZigClangDeclUnresolvedUsingTypename:
2556 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C UnresolvedUsingTypename");
2557 return ErrorUnexpected;
2558 case ZigClangDeclUsing:
2559 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Using");
2560 return ErrorUnexpected;
2561 case ZigClangDeclUsingDirective:
2562 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C UsingDirective");
2563 return ErrorUnexpected;
2564 case ZigClangDeclUsingPack:
2565 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C UsingPack");
2566 return ErrorUnexpected;
2567 case ZigClangDeclUsingShadow:
2568 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C UsingShadow");
2569 return ErrorUnexpected;
2570 case ZigClangDeclConstructorUsingShadow:
2571 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ConstructorUsingShadow");
2572 return ErrorUnexpected;
2573 case ZigClangDeclBinding:
2574 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Binding");
2575 return ErrorUnexpected;
2576 case ZigClangDeclField:
2577 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Field");
2578 return ErrorUnexpected;
2579 case ZigClangDeclObjCAtDefsField:
2580 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCAtDefsField");
2581 return ErrorUnexpected;
2582 case ZigClangDeclObjCIvar:
2583 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCIvar");
2584 return ErrorUnexpected;
2585 case ZigClangDeclFunction:
2586 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Function");
2587 return ErrorUnexpected;
2588 case ZigClangDeclCXXDeductionGuide:
2589 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C CXXDeductionGuide");
2590 return ErrorUnexpected;
2591 case ZigClangDeclCXXMethod:
2592 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C CXXMethod");
2593 return ErrorUnexpected;
2594 case ZigClangDeclCXXConstructor:
2595 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C CXXConstructor");
2596 return ErrorUnexpected;
2597 case ZigClangDeclCXXConversion:
2598 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C CXXConversion");
2599 return ErrorUnexpected;
2600 case ZigClangDeclCXXDestructor:
2601 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C CXXDestructor");
2602 return ErrorUnexpected;
2603 case ZigClangDeclMSProperty:
2604 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C MSProperty");
2605 return ErrorUnexpected;
2606 case ZigClangDeclNonTypeTemplateParm:
2607 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C NonTypeTemplateParm");
2608 return ErrorUnexpected;
2609 case ZigClangDeclDecomposition:
2610 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Decomposition");
2611 return ErrorUnexpected;
2612 case ZigClangDeclImplicitParam:
2613 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ImplicitParam");
2614 return ErrorUnexpected;
2615 case ZigClangDeclOMPCapturedExpr:
2616 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C OMPCapturedExpr");
2617 return ErrorUnexpected;
2618 case ZigClangDeclParmVar:
2619 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ParmVar");
2620 return ErrorUnexpected;
2621 case ZigClangDeclVarTemplateSpecialization:
2622 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C VarTemplateSpecialization");
2623 return ErrorUnexpected;
2624 case ZigClangDeclVarTemplatePartialSpecialization:
2625 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C VarTemplatePartialSpecialization");
2626 return ErrorUnexpected;
2627 case ZigClangDeclEnumConstant:
2628 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C EnumConstant");
2629 return ErrorUnexpected;
2630 case ZigClangDeclIndirectField:
2631 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C IndirectField");
2632 return ErrorUnexpected;
2633 case ZigClangDeclOMPDeclareReduction:
2634 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C OMPDeclareReduction");
2635 return ErrorUnexpected;
2636 case ZigClangDeclUnresolvedUsingValue:
2637 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C UnresolvedUsingValue");
2638 return ErrorUnexpected;
2639 case ZigClangDeclOMPRequires:
2640 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C OMPRequires");
2641 return ErrorUnexpected;
2642 case ZigClangDeclOMPThreadPrivate:
2643 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C OMPThreadPrivate");
2644 return ErrorUnexpected;
2645 case ZigClangDeclObjCPropertyImpl:
2646 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C ObjCPropertyImpl");
2647 return ErrorUnexpected;
2648 case ZigClangDeclPragmaComment:
2649 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C PragmaComment");
2650 return ErrorUnexpected;
2651 case ZigClangDeclPragmaDetectMismatch:
2652 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C PragmaDetectMismatch");
2653 return ErrorUnexpected;
2654 case ZigClangDeclStaticAssert:
2655 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C StaticAssert");
2656 return ErrorUnexpected;
2657 case ZigClangDeclTranslationUnit:
2658 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C TranslationUnit");
2659 return ErrorUnexpected;
2660 case ZigClangDeclConcept:
2661 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C Concept");
2662 return ErrorUnexpected;
2663 case ZigClangDeclOMPDeclareMapper:
2664 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C OMPDeclareMapper");
2665 return ErrorUnexpected;
2666 case ZigClangDeclOMPAllocate:
2667 emit_warning(c, ZigClangDeclStmt_getBeginLoc(stmt), "TODO handle C OMPAllocate");
2668 return ErrorUnexpected;
2669 }
2670 zig_unreachable();
2671 }
2672
2673 *out_scope = scope;
2674 return ErrorNone;
2675}
2676
2677static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) {
2678 AstNode *tag_type = trans_create_node_builtin_fn_call_str(c, "TagType");
2679 tag_type->data.fn_call_expr.params.append(enum_type);
2680
2681 // @TagType(Enum)(0)
2682 AstNode *zero = trans_create_node_unsigned_negative(c, 0, false);
2683 AstNode *casted_zero = trans_create_node_cast(c, tag_type, zero);
2684
2685 // @bitCast(Enum, @TagType(Enum)(0))
2686 AstNode *bitcast = trans_create_node_builtin_fn_call_str(c, "bitCast");
2687 bitcast->data.fn_call_expr.params.append(enum_type);
2688 bitcast->data.fn_call_expr.params.append(casted_zero);
2689
2690 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
2691}
2692
2693static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr, TransLRValue lrval) {
2694 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
2695 if (res == nullptr)
2696 return nullptr;
2697
2698 switch (res->type) {
2699 case NodeTypeBinOpExpr:
2700 switch (res->data.bin_op_expr.bin_op) {
2701 case BinOpTypeBoolOr:
2702 case BinOpTypeBoolAnd:
2703 case BinOpTypeCmpEq:
2704 case BinOpTypeCmpNotEq:
2705 case BinOpTypeCmpLessThan:
2706 case BinOpTypeCmpGreaterThan:
2707 case BinOpTypeCmpLessOrEq:
2708 case BinOpTypeCmpGreaterOrEq:
2709 return res;
2710 default:
2711 break;
2712 }
2713
2714 case NodeTypePrefixOpExpr:
2715 switch (res->data.prefix_op_expr.prefix_op) {
2716 case PrefixOpBoolNot:
2717 return res;
2718 default:
2719 break;
2720 }
2721
2722 case NodeTypeBoolLiteral:
2723 return res;
2724
2725 default:
2726 break;
2727 }
2728
2729
2730 const ZigClangType *ty = ZigClangQualType_getTypePtr(get_expr_qual_type_before_implicit_cast(c, expr));
2731 auto classs = ZigClangType_getTypeClass(ty);
2732 switch (classs) {
2733 case ZigClangType_Builtin:
2734 {
2735 const ZigClangBuiltinType *builtin_ty = reinterpret_cast<const ZigClangBuiltinType*>(ty);
2736 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
2737 case ZigClangBuiltinTypeBool:
2738 case ZigClangBuiltinTypeChar_U:
2739 case ZigClangBuiltinTypeUChar:
2740 case ZigClangBuiltinTypeChar_S:
2741 case ZigClangBuiltinTypeSChar:
2742 case ZigClangBuiltinTypeUShort:
2743 case ZigClangBuiltinTypeUInt:
2744 case ZigClangBuiltinTypeULong:
2745 case ZigClangBuiltinTypeULongLong:
2746 case ZigClangBuiltinTypeShort:
2747 case ZigClangBuiltinTypeInt:
2748 case ZigClangBuiltinTypeLong:
2749 case ZigClangBuiltinTypeLongLong:
2750 case ZigClangBuiltinTypeUInt128:
2751 case ZigClangBuiltinTypeInt128:
2752 case ZigClangBuiltinTypeFloat:
2753 case ZigClangBuiltinTypeDouble:
2754 case ZigClangBuiltinTypeFloat128:
2755 case ZigClangBuiltinTypeLongDouble:
2756 case ZigClangBuiltinTypeWChar_U:
2757 case ZigClangBuiltinTypeChar8:
2758 case ZigClangBuiltinTypeChar16:
2759 case ZigClangBuiltinTypeChar32:
2760 case ZigClangBuiltinTypeWChar_S:
2761 case ZigClangBuiltinTypeFloat16:
2762 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2763 case ZigClangBuiltinTypeNullPtr:
2764 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2765 trans_create_node(c, NodeTypeNullLiteral));
2766
2767 case ZigClangBuiltinTypeVoid:
2768 case ZigClangBuiltinTypeHalf:
2769 case ZigClangBuiltinTypeObjCId:
2770 case ZigClangBuiltinTypeObjCClass:
2771 case ZigClangBuiltinTypeObjCSel:
2772 case ZigClangBuiltinTypeOMPArraySection:
2773 case ZigClangBuiltinTypeDependent:
2774 case ZigClangBuiltinTypeOverload:
2775 case ZigClangBuiltinTypeBoundMember:
2776 case ZigClangBuiltinTypePseudoObject:
2777 case ZigClangBuiltinTypeUnknownAny:
2778 case ZigClangBuiltinTypeBuiltinFn:
2779 case ZigClangBuiltinTypeARCUnbridgedCast:
2780 case ZigClangBuiltinTypeOCLImage1dRO:
2781 case ZigClangBuiltinTypeOCLImage1dArrayRO:
2782 case ZigClangBuiltinTypeOCLImage1dBufferRO:
2783 case ZigClangBuiltinTypeOCLImage2dRO:
2784 case ZigClangBuiltinTypeOCLImage2dArrayRO:
2785 case ZigClangBuiltinTypeOCLImage2dDepthRO:
2786 case ZigClangBuiltinTypeOCLImage2dArrayDepthRO:
2787 case ZigClangBuiltinTypeOCLImage2dMSAARO:
2788 case ZigClangBuiltinTypeOCLImage2dArrayMSAARO:
2789 case ZigClangBuiltinTypeOCLImage2dMSAADepthRO:
2790 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRO:
2791 case ZigClangBuiltinTypeOCLImage3dRO:
2792 case ZigClangBuiltinTypeOCLImage1dWO:
2793 case ZigClangBuiltinTypeOCLImage1dArrayWO:
2794 case ZigClangBuiltinTypeOCLImage1dBufferWO:
2795 case ZigClangBuiltinTypeOCLImage2dWO:
2796 case ZigClangBuiltinTypeOCLImage2dArrayWO:
2797 case ZigClangBuiltinTypeOCLImage2dDepthWO:
2798 case ZigClangBuiltinTypeOCLImage2dArrayDepthWO:
2799 case ZigClangBuiltinTypeOCLImage2dMSAAWO:
2800 case ZigClangBuiltinTypeOCLImage2dArrayMSAAWO:
2801 case ZigClangBuiltinTypeOCLImage2dMSAADepthWO:
2802 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthWO:
2803 case ZigClangBuiltinTypeOCLImage3dWO:
2804 case ZigClangBuiltinTypeOCLImage1dRW:
2805 case ZigClangBuiltinTypeOCLImage1dArrayRW:
2806 case ZigClangBuiltinTypeOCLImage1dBufferRW:
2807 case ZigClangBuiltinTypeOCLImage2dRW:
2808 case ZigClangBuiltinTypeOCLImage2dArrayRW:
2809 case ZigClangBuiltinTypeOCLImage2dDepthRW:
2810 case ZigClangBuiltinTypeOCLImage2dArrayDepthRW:
2811 case ZigClangBuiltinTypeOCLImage2dMSAARW:
2812 case ZigClangBuiltinTypeOCLImage2dArrayMSAARW:
2813 case ZigClangBuiltinTypeOCLImage2dMSAADepthRW:
2814 case ZigClangBuiltinTypeOCLImage2dArrayMSAADepthRW:
2815 case ZigClangBuiltinTypeOCLImage3dRW:
2816 case ZigClangBuiltinTypeOCLSampler:
2817 case ZigClangBuiltinTypeOCLEvent:
2818 case ZigClangBuiltinTypeOCLClkEvent:
2819 case ZigClangBuiltinTypeOCLQueue:
2820 case ZigClangBuiltinTypeOCLReserveID:
2821 case ZigClangBuiltinTypeShortAccum:
2822 case ZigClangBuiltinTypeAccum:
2823 case ZigClangBuiltinTypeLongAccum:
2824 case ZigClangBuiltinTypeUShortAccum:
2825 case ZigClangBuiltinTypeUAccum:
2826 case ZigClangBuiltinTypeULongAccum:
2827 case ZigClangBuiltinTypeShortFract:
2828 case ZigClangBuiltinTypeFract:
2829 case ZigClangBuiltinTypeLongFract:
2830 case ZigClangBuiltinTypeUShortFract:
2831 case ZigClangBuiltinTypeUFract:
2832 case ZigClangBuiltinTypeULongFract:
2833 case ZigClangBuiltinTypeSatShortAccum:
2834 case ZigClangBuiltinTypeSatAccum:
2835 case ZigClangBuiltinTypeSatLongAccum:
2836 case ZigClangBuiltinTypeSatUShortAccum:
2837 case ZigClangBuiltinTypeSatUAccum:
2838 case ZigClangBuiltinTypeSatULongAccum:
2839 case ZigClangBuiltinTypeSatShortFract:
2840 case ZigClangBuiltinTypeSatFract:
2841 case ZigClangBuiltinTypeSatLongFract:
2842 case ZigClangBuiltinTypeSatUShortFract:
2843 case ZigClangBuiltinTypeSatUFract:
2844 case ZigClangBuiltinTypeSatULongFract:
2845 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMcePayload:
2846 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImePayload:
2847 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefPayload:
2848 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicPayload:
2849 case ZigClangBuiltinTypeOCLIntelSubgroupAVCMceResult:
2850 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResult:
2851 case ZigClangBuiltinTypeOCLIntelSubgroupAVCRefResult:
2852 case ZigClangBuiltinTypeOCLIntelSubgroupAVCSicResult:
2853 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultSingleRefStreamout:
2854 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeResultDualRefStreamout:
2855 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeSingleRefStreamin:
2856 case ZigClangBuiltinTypeOCLIntelSubgroupAVCImeDualRefStreamin:
2857 return res;
2858 }
2859 break;
2860 }
2861 case ZigClangType_Pointer:
2862 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2863
2864 case ZigClangType_Typedef:
2865 {
2866 const ZigClangTypedefType *typedef_ty = reinterpret_cast<const ZigClangTypedefType*>(ty);
2867 const ZigClangTypedefNameDecl *typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
2868 auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl));
2869 if (existing_entry) {
2870 return existing_entry->value;
2871 }
2872
2873 return res;
2874 }
2875
2876 case ZigClangType_Enum:
2877 {
2878 const ZigClangEnumType *enum_ty = reinterpret_cast<const ZigClangEnumType *>(ty);
2879 AstNode *enum_type = resolve_enum_decl(c, ZigClangEnumType_getDecl(enum_ty));
2880 return to_enum_zero_cmp(c, res, enum_type);
2881 }
2882
2883 case ZigClangType_Elaborated:
2884 {
2885 const ZigClangElaboratedType *elaborated_ty = reinterpret_cast<const ZigClangElaboratedType*>(ty);
2886 switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) {
2887 case ZigClangETK_Enum: {
2888 AstNode *enum_type = trans_qual_type(c, ZigClangElaboratedType_getNamedType(elaborated_ty),
2889 ZigClangExpr_getBeginLoc(expr));
2890 return to_enum_zero_cmp(c, res, enum_type);
2891 }
2892 case ZigClangETK_Struct:
2893 case ZigClangETK_Union:
2894 case ZigClangETK_Interface:
2895 case ZigClangETK_Class:
2896 case ZigClangETK_Typename:
2897 case ZigClangETK_None:
2898 return res;
2899 }
2900 }
2901
2902 case ZigClangType_FunctionProto:
2903 case ZigClangType_Record:
2904 case ZigClangType_ConstantArray:
2905 case ZigClangType_Paren:
2906 case ZigClangType_Decayed:
2907 case ZigClangType_Attributed:
2908 case ZigClangType_IncompleteArray:
2909 case ZigClangType_BlockPointer:
2910 case ZigClangType_LValueReference:
2911 case ZigClangType_RValueReference:
2912 case ZigClangType_MemberPointer:
2913 case ZigClangType_VariableArray:
2914 case ZigClangType_DependentSizedArray:
2915 case ZigClangType_DependentSizedExtVector:
2916 case ZigClangType_Vector:
2917 case ZigClangType_ExtVector:
2918 case ZigClangType_FunctionNoProto:
2919 case ZigClangType_UnresolvedUsing:
2920 case ZigClangType_Adjusted:
2921 case ZigClangType_TypeOfExpr:
2922 case ZigClangType_TypeOf:
2923 case ZigClangType_Decltype:
2924 case ZigClangType_UnaryTransform:
2925 case ZigClangType_TemplateTypeParm:
2926 case ZigClangType_SubstTemplateTypeParm:
2927 case ZigClangType_SubstTemplateTypeParmPack:
2928 case ZigClangType_TemplateSpecialization:
2929 case ZigClangType_Auto:
2930 case ZigClangType_InjectedClassName:
2931 case ZigClangType_DependentName:
2932 case ZigClangType_DependentTemplateSpecialization:
2933 case ZigClangType_PackExpansion:
2934 case ZigClangType_ObjCObject:
2935 case ZigClangType_ObjCInterface:
2936 case ZigClangType_Complex:
2937 case ZigClangType_ObjCObjectPointer:
2938 case ZigClangType_Atomic:
2939 case ZigClangType_Pipe:
2940 case ZigClangType_ObjCTypeParam:
2941 case ZigClangType_DeducedTemplateSpecialization:
2942 case ZigClangType_DependentAddressSpace:
2943 case ZigClangType_DependentVector:
2944 case ZigClangType_MacroQualified:
2945 return res;
2946 }
2947 zig_unreachable();
2948}
2949
2950static AstNode *trans_while_loop(Context *c, TransScope *scope, const ZigClangWhileStmt *stmt) {
2951 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
2952
2953 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope,
2954 ZigClangWhileStmt_getCond(stmt), TransRValue);
2955 if (while_scope->node->data.while_expr.condition == nullptr)
2956 return nullptr;
2957
2958 TransScope *body_scope = trans_stmt(c, &while_scope->base, ZigClangWhileStmt_getBody(stmt),
2959 &while_scope->node->data.while_expr.body);
2960 if (body_scope == nullptr)
2961 return nullptr;
2962
2963 return while_scope->node;
2964}
2965
2966static AstNode *trans_if_statement(Context *c, TransScope *scope, const ZigClangIfStmt *stmt) {
2967 // if (c) t
2968 // if (c) t else e
2969 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
2970
2971 TransScope *then_scope = trans_stmt(c, scope, ZigClangIfStmt_getThen(stmt), &if_node->data.if_bool_expr.then_block);
2972 if (then_scope == nullptr)
2973 return nullptr;
2974
2975 if (ZigClangIfStmt_getElse(stmt) != nullptr) {
2976 TransScope *else_scope = trans_stmt(c, scope, ZigClangIfStmt_getElse(stmt), &if_node->data.if_bool_expr.else_node);
2977 if (else_scope == nullptr)
2978 return nullptr;
2979 }
2980
2981 if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, ZigClangIfStmt_getCond(stmt),
2982 TransRValue);
2983 if (if_node->data.if_bool_expr.condition == nullptr)
2984 return nullptr;
2985
2986 return if_node;
2987}
2988
2989static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangCallExpr *stmt) {
2990 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
2991
2992 AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, ZigClangCallExpr_getCallee(stmt), TransRValue);
2993 if (callee_raw_node == nullptr)
2994 return nullptr;
2995
2996 bool is_ptr = false;
2997 const ZigClangFunctionProtoType *fn_ty = qual_type_get_fn_proto(
2998 ZigClangExpr_getType(ZigClangCallExpr_getCallee(stmt)), &is_ptr);
2999 AstNode *callee_node = nullptr;
3000 if (is_ptr && fn_ty) {
3001 if (ZigClangExpr_getStmtClass(ZigClangCallExpr_getCallee(stmt)) == ZigClangStmt_ImplicitCastExprClass) {
3002 const ZigClangImplicitCastExpr *implicit_cast = reinterpret_cast<const ZigClangImplicitCastExpr *>(
3003 ZigClangCallExpr_getCallee(stmt));
3004 if (ZigClangImplicitCastExpr_getCastKind(implicit_cast) == ZigClangCK_FunctionToPointerDecay) {
3005 const ZigClangExpr *subexpr = ZigClangImplicitCastExpr_getSubExpr(implicit_cast);
3006 if (ZigClangExpr_getStmtClass(subexpr) == ZigClangStmt_DeclRefExprClass) {
3007 const ZigClangDeclRefExpr *decl_ref = reinterpret_cast<const ZigClangDeclRefExpr *>(subexpr);
3008 const ZigClangNamedDecl *named_decl = ZigClangDeclRefExpr_getFoundDecl(decl_ref);
3009 if (ZigClangDecl_getKind((const ZigClangDecl *)named_decl) == ZigClangDeclFunction) {
3010 callee_node = callee_raw_node;
3011 }
3012 }
3013 }
3014 }
3015 if (callee_node == nullptr) {
3016 callee_node = trans_create_node_unwrap_null(c, callee_raw_node);
3017 }
3018 } else {
3019 callee_node = callee_raw_node;
3020 }
3021
3022 node->data.fn_call_expr.fn_ref_expr = callee_node;
3023
3024 unsigned num_args = ZigClangCallExpr_getNumArgs(stmt);
3025 const ZigClangExpr * const* args = ZigClangCallExpr_getArgs(stmt);
3026 for (unsigned i = 0; i < num_args; i += 1) {
3027 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
3028 if (arg_node == nullptr)
3029 return nullptr;
3030
3031 node->data.fn_call_expr.params.append(arg_node);
3032 }
3033
3034 if (result_used == ResultUsedNo && fn_ty &&
3035 !ZigClangType_isVoidType(qual_type_canon(ZigClangFunctionProtoType_getReturnType(fn_ty))))
3036 {
3037 node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node);
3038 }
3039
3040 return node;
3041}
3042
3043static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope,
3044 const ZigClangMemberExpr *stmt)
3045{
3046 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, ZigClangMemberExpr_getBase(stmt), TransRValue);
3047 if (container_node == nullptr)
3048 return nullptr;
3049
3050 if (ZigClangMemberExpr_isArrow(stmt)) {
3051 container_node = trans_create_node_ptr_deref(c, container_node);
3052 }
3053
3054 const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)ZigClangMemberExpr_getMemberDecl(stmt));
3055
3056 AstNode *node = trans_create_node_field_access_str(c, container_node, name);
3057 return maybe_suppress_result(c, result_used, node);
3058}
3059
3060static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, TransScope *scope,
3061 const ZigClangArraySubscriptExpr *stmt)
3062{
3063 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, ZigClangArraySubscriptExpr_getBase(stmt),
3064 TransRValue);
3065 if (container_node == nullptr)
3066 return nullptr;
3067
3068 AstNode *idx_node = trans_expr(c, ResultUsedYes, scope, ZigClangArraySubscriptExpr_getIdx(stmt), TransRValue);
3069 if (idx_node == nullptr)
3070 return nullptr;
3071
3072
3073 AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr);
3074 node->data.array_access_expr.array_ref_expr = container_node;
3075 node->data.array_access_expr.subscript = idx_node;
3076 return maybe_suppress_result(c, result_used, node);
3077}
3078
3079static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
3080 const ZigClangCStyleCastExpr *stmt, TransLRValue lrvalue)
3081{
3082 AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, ZigClangCStyleCastExpr_getSubExpr(stmt), lrvalue);
3083 if (sub_expr_node == nullptr)
3084 return nullptr;
3085
3086 AstNode *cast = trans_c_cast(c, ZigClangCStyleCastExpr_getBeginLoc(stmt), ZigClangCStyleCastExpr_getType(stmt),
3087 ZigClangExpr_getType(ZigClangCStyleCastExpr_getSubExpr(stmt)), sub_expr_node);
3088 if (cast == nullptr)
3089 return nullptr;
3090
3091 return maybe_suppress_result(c, result_used, cast);
3092}
3093
3094static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used,
3095 TransScope *scope, const ZigClangUnaryExprOrTypeTraitExpr *stmt)
3096{
3097 AstNode *type_node = trans_qual_type(c, ZigClangUnaryExprOrTypeTraitExpr_getTypeOfArgument(stmt),
3098 ZigClangUnaryExprOrTypeTraitExpr_getBeginLoc(stmt));
3099 if (type_node == nullptr)
3100 return nullptr;
3101
3102 AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf");
3103 node->data.fn_call_expr.params.append(type_node);
3104 return maybe_suppress_result(c, result_used, node);
3105}
3106
3107static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const ZigClangDoStmt *stmt) {
3108 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
3109
3110 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
3111
3112 AstNode *body_node;
3113 TransScope *child_scope;
3114 if (ZigClangStmt_getStmtClass(ZigClangDoStmt_getBody(stmt)) == ZigClangStmt_CompoundStmtClass) {
3115 // there's already a block in C, so we'll append our condition to it.
3116 // c: do {
3117 // c: a;
3118 // c: b;
3119 // c: } while(c);
3120 // zig: while (true) {
3121 // zig: a;
3122 // zig: b;
3123 // zig: if (!cond) break;
3124 // zig: }
3125
3126 // We call the low level function so that we can set child_scope to the scope of the generated block.
3127 if (trans_stmt_extra(c, &while_scope->base, ZigClangDoStmt_getBody(stmt), ResultUsedNo, TransRValue,
3128 &body_node, nullptr, &child_scope))
3129 {
3130 return nullptr;
3131 }
3132 assert(body_node->type == NodeTypeBlock);
3133 } else {
3134 // the C statement is without a block, so we need to create a block to contain it.
3135 // c: do
3136 // c: a;
3137 // c: while(c);
3138 // zig: while (true) {
3139 // zig: a;
3140 // zig: if (!cond) break;
3141 // zig: }
3142 TransScopeBlock *child_block_scope = trans_scope_block_create(c, &while_scope->base);
3143 body_node = child_block_scope->node;
3144 AstNode *child_statement;
3145 child_scope = trans_stmt(c, &child_block_scope->base, ZigClangDoStmt_getBody(stmt), &child_statement);
3146 if (child_scope == nullptr) return nullptr;
3147 if (child_statement != nullptr) {
3148 body_node->data.block.statements.append(child_statement);
3149 }
3150 }
3151
3152 // if (!cond) break;
3153 AstNode *condition_node = trans_expr(c, ResultUsedYes, child_scope, ZigClangDoStmt_getCond(stmt), TransRValue);
3154 if (condition_node == nullptr) return nullptr;
3155 AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr);
3156 terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node);
3157 terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak);
3158
3159 assert(terminator_node != nullptr);
3160 body_node->data.block.statements.append(terminator_node);
3161
3162 while_scope->node->data.while_expr.body = body_node;
3163
3164 return while_scope->node;
3165}
3166
3167static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ZigClangForStmt *stmt) {
3168 AstNode *loop_block_node;
3169 TransScopeWhile *while_scope;
3170 TransScope *cond_scope;
3171 const ZigClangStmt *init_stmt = ZigClangForStmt_getInit(stmt);
3172 if (init_stmt == nullptr) {
3173 while_scope = trans_scope_while_create(c, parent_scope);
3174 loop_block_node = while_scope->node;
3175 cond_scope = parent_scope;
3176 } else {
3177 TransScopeBlock *child_scope = trans_scope_block_create(c, parent_scope);
3178 loop_block_node = child_scope->node;
3179
3180 AstNode *vars_node;
3181 cond_scope = trans_stmt(c, &child_scope->base, init_stmt, &vars_node);
3182 if (cond_scope == nullptr)
3183 return nullptr;
3184 if (vars_node != nullptr)
3185 child_scope->node->data.block.statements.append(vars_node);
3186
3187 while_scope = trans_scope_while_create(c, cond_scope);
3188
3189 child_scope->node->data.block.statements.append(while_scope->node);
3190 }
3191
3192 const ZigClangExpr *cond_expr = ZigClangForStmt_getCond(stmt);
3193 if (cond_expr == nullptr) {
3194 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
3195 } else {
3196 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope,
3197 cond_expr, TransRValue);
3198
3199 if (while_scope->node->data.while_expr.condition == nullptr)
3200 return nullptr;
3201 }
3202
3203 const ZigClangExpr *inc_expr = ZigClangForStmt_getInc(stmt);
3204 if (inc_expr != nullptr) {
3205 AstNode *inc_node = trans_expr(c, ResultUsedNo, cond_scope, inc_expr, TransRValue);
3206 if (inc_node == nullptr)
3207 return nullptr;
3208 while_scope->node->data.while_expr.continue_expr = inc_node;
3209 }
3210
3211 AstNode *body_statement;
3212 TransScope *body_scope = trans_stmt(c, &while_scope->base, ZigClangForStmt_getBody(stmt), &body_statement);
3213 if (body_scope == nullptr)
3214 return nullptr;
3215
3216 if (body_statement == nullptr) {
3217 while_scope->node->data.while_expr.body = trans_create_node(c, NodeTypeBlock);
3218 } else {
3219 while_scope->node->data.while_expr.body = body_statement;
3220 }
3221
3222 return loop_block_node;
3223}
3224
3225static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const ZigClangSwitchStmt *stmt) {
3226 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
3227
3228 TransScopeSwitch *switch_scope;
3229
3230 const ZigClangDeclStmt *var_decl_stmt = ZigClangSwitchStmt_getConditionVariableDeclStmt(stmt);
3231 if (var_decl_stmt == nullptr) {
3232 switch_scope = trans_scope_switch_create(c, &block_scope->base);
3233 } else {
3234 AstNode *vars_node;
3235 TransScope *var_scope = trans_stmt(c, &block_scope->base, (const ZigClangStmt *)var_decl_stmt, &vars_node);
3236 if (var_scope == nullptr)
3237 return nullptr;
3238 if (vars_node != nullptr)
3239 block_scope->node->data.block.statements.append(vars_node);
3240 switch_scope = trans_scope_switch_create(c, var_scope);
3241 }
3242 block_scope->node->data.block.statements.append(switch_scope->switch_node);
3243
3244 // TODO avoid name collisions
3245 Buf *end_label_name = buf_create_from_str("__switch");
3246 switch_scope->end_label_name = end_label_name;
3247 block_scope->node->data.block.name = end_label_name;
3248
3249 const ZigClangExpr *cond_expr = ZigClangSwitchStmt_getCond(stmt);
3250 assert(cond_expr != nullptr);
3251
3252 AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);
3253 if (expr_node == nullptr)
3254 return nullptr;
3255 switch_scope->switch_node->data.switch_expr.expr = expr_node;
3256
3257 AstNode *body_node;
3258 const ZigClangStmt *body_stmt = ZigClangSwitchStmt_getBody(stmt);
3259 if (ZigClangStmt_getStmtClass(body_stmt) == ZigClangStmt_CompoundStmtClass) {
3260 if (trans_compound_stmt_inline(c, &switch_scope->base, (const ZigClangCompoundStmt *)body_stmt,
3261 block_scope->node, nullptr))
3262 {
3263 return nullptr;
3264 }
3265 } else {
3266 TransScope *body_scope = trans_stmt(c, &switch_scope->base, body_stmt, &body_node);
3267 if (body_scope == nullptr)
3268 return nullptr;
3269 if (body_node != nullptr)
3270 block_scope->node->data.block.statements.append(body_node);
3271 }
3272
3273 if (!switch_scope->found_default && !ZigClangSwitchStmt_isAllEnumCasesCovered(stmt)) {
3274 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
3275 prong_node->data.switch_prong.expr = trans_create_node_break(c, end_label_name, nullptr);
3276 switch_scope->switch_node->data.switch_expr.prongs.append(prong_node);
3277 }
3278
3279 return block_scope->node;
3280}
3281
3282static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
3283 while (scope != nullptr) {
3284 if (scope->id == TransScopeIdSwitch) {
3285 return (TransScopeSwitch *)scope;
3286 }
3287 scope = scope->parent;
3288 }
3289 return nullptr;
3290}
3291
3292static int trans_switch_case(Context *c, TransScope *parent_scope, const ZigClangCaseStmt *stmt, AstNode **out_node,
3293 TransScope **out_scope) {
3294 *out_node = nullptr;
3295
3296 if (ZigClangCaseStmt_getRHS(stmt) != nullptr) {
3297 emit_warning(c, ZigClangCaseStmt_getBeginLoc(stmt), "TODO support GNU switch case a ... b extension");
3298 return ErrorUnexpected;
3299 }
3300
3301 TransScopeSwitch *switch_scope = trans_scope_switch_find(parent_scope);
3302 assert(switch_scope != nullptr);
3303
3304 Buf *label_name = buf_sprintf("__case_%" PRIu32, switch_scope->case_index);
3305 switch_scope->case_index += 1;
3306
3307 {
3308 // Add the prong
3309 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
3310 AstNode *item_node = trans_expr(c, ResultUsedYes, &switch_scope->base, ZigClangCaseStmt_getLHS(stmt),
3311 TransRValue);
3312 if (item_node == nullptr)
3313 return ErrorUnexpected;
3314 prong_node->data.switch_prong.items.append(item_node);
3315 prong_node->data.switch_prong.expr = trans_create_node_break(c, label_name, nullptr);
3316 switch_scope->switch_node->data.switch_expr.prongs.append(prong_node);
3317 }
3318
3319 TransScopeBlock *scope_block = trans_scope_block_find(parent_scope);
3320
3321 AstNode *case_block = trans_create_node(c, NodeTypeBlock);
3322 case_block->data.block.name = label_name;
3323 case_block->data.block.statements = scope_block->node->data.block.statements;
3324 scope_block->node->data.block.statements = {0};
3325 scope_block->node->data.block.statements.append(case_block);
3326
3327 AstNode *sub_stmt_node;
3328 TransScope *new_scope = trans_stmt(c, parent_scope, ZigClangCaseStmt_getSubStmt(stmt), &sub_stmt_node);
3329 if (new_scope == nullptr)
3330 return ErrorUnexpected;
3331 if (sub_stmt_node != nullptr)
3332 scope_block->node->data.block.statements.append(sub_stmt_node);
3333
3334 *out_scope = new_scope;
3335 return ErrorNone;
3336}
3337
3338static int trans_switch_default(Context *c, TransScope *parent_scope, const ZigClangDefaultStmt *stmt,
3339 AstNode **out_node, TransScope **out_scope)
3340{
3341 *out_node = nullptr;
3342
3343 TransScopeSwitch *switch_scope = trans_scope_switch_find(parent_scope);
3344 assert(switch_scope != nullptr);
3345
3346 Buf *label_name = buf_sprintf("__default");
3347
3348 {
3349 // Add the prong
3350 AstNode *prong_node = trans_create_node(c, NodeTypeSwitchProng);
3351 prong_node->data.switch_prong.expr = trans_create_node_break(c, label_name, nullptr);
3352 switch_scope->switch_node->data.switch_expr.prongs.append(prong_node);
3353 switch_scope->found_default = true;
3354 }
3355
3356 TransScopeBlock *scope_block = trans_scope_block_find(parent_scope);
3357
3358 AstNode *case_block = trans_create_node(c, NodeTypeBlock);
3359 case_block->data.block.name = label_name;
3360 case_block->data.block.statements = scope_block->node->data.block.statements;
3361 scope_block->node->data.block.statements = {0};
3362 scope_block->node->data.block.statements.append(case_block);
3363
3364 AstNode *sub_stmt_node;
3365 TransScope *new_scope = trans_stmt(c, parent_scope, ZigClangDefaultStmt_getSubStmt(stmt), &sub_stmt_node);
3366 if (new_scope == nullptr)
3367 return ErrorUnexpected;
3368 if (sub_stmt_node != nullptr)
3369 scope_block->node->data.block.statements.append(sub_stmt_node);
3370
3371 *out_scope = new_scope;
3372 return ErrorNone;
3373}
3374
3375static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransScope *scope,
3376 const ZigClangStringLiteral *stmt)
3377{
3378 switch (ZigClangStringLiteral_getKind(stmt)) {
3379 case ZigClangStringLiteral_StringKind_Ascii:
3380 case ZigClangStringLiteral_StringKind_UTF8: {
3381 size_t str_len;
3382 const char *str_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &str_len);
3383 AstNode *node = trans_create_node_str_lit(c, buf_create_from_mem(str_ptr, str_len));
3384 return maybe_suppress_result(c, result_used, node);
3385 }
3386 case ZigClangStringLiteral_StringKind_UTF16:
3387 emit_warning(c, ZigClangStmt_getBeginLoc((const ZigClangStmt *)stmt), "TODO support UTF16 string literals");
3388 return nullptr;
3389 case ZigClangStringLiteral_StringKind_UTF32:
3390 emit_warning(c, ZigClangStmt_getBeginLoc((const ZigClangStmt *)stmt), "TODO support UTF32 string literals");
3391 return nullptr;
3392 case ZigClangStringLiteral_StringKind_Wide:
3393 emit_warning(c, ZigClangStmt_getBeginLoc((const ZigClangStmt *)stmt), "TODO support wide string literals");
3394 return nullptr;
3395 }
3396 zig_unreachable();
3397}
3398
3399static AstNode *trans_break_stmt(Context *c, TransScope *scope, const ZigClangBreakStmt *stmt) {
3400 TransScope *cur_scope = scope;
3401 while (cur_scope != nullptr) {
3402 if (cur_scope->id == TransScopeIdWhile) {
3403 return trans_create_node(c, NodeTypeBreak);
3404 } else if (cur_scope->id == TransScopeIdSwitch) {
3405 TransScopeSwitch *switch_scope = (TransScopeSwitch *)cur_scope;
3406 return trans_create_node_break(c, switch_scope->end_label_name, nullptr);
3407 }
3408 cur_scope = cur_scope->parent;
3409 }
3410 zig_unreachable();
3411}
3412
3413static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ZigClangContinueStmt *stmt) {
3414 return trans_create_node(c, NodeTypeContinue);
3415}
3416
3417static AstNode *trans_predefined_expr(Context *c, ResultUsed result_used, TransScope *scope,
3418 const ZigClangPredefinedExpr *expr)
3419{
3420 return trans_string_literal(c, result_used, scope, ZigClangPredefinedExpr_getFunctionName(expr));
3421}
3422
3423static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_scope, AstNode *result_node) {
3424 if (result_node == nullptr)
3425 return ErrorUnexpected;
3426 *out_node = result_node;
3427 if (out_scope != nullptr)
3428 *out_scope = in_scope;
3429 return ErrorNone;
3430}
3431
3432static int trans_stmt_extra(Context *c, TransScope *scope, const ZigClangStmt *stmt,
3433 ResultUsed result_used, TransLRValue lrvalue,
3434 AstNode **out_node, TransScope **out_child_scope,
3435 TransScope **out_node_scope)
3436{
3437 ZigClangStmtClass sc = ZigClangStmt_getStmtClass(stmt);
3438 switch (sc) {
3439 case ZigClangStmt_ReturnStmtClass:
3440 return wrap_stmt(out_node, out_child_scope, scope,
3441 trans_return_stmt(c, scope, (const ZigClangReturnStmt *)stmt));
3442 case ZigClangStmt_CompoundStmtClass:
3443 return wrap_stmt(out_node, out_child_scope, scope,
3444 trans_compound_stmt(c, scope, (const ZigClangCompoundStmt *)stmt, out_node_scope));
3445 case ZigClangStmt_IntegerLiteralClass:
3446 return wrap_stmt(out_node, out_child_scope, scope,
3447 trans_integer_literal(c, result_used, (const ZigClangIntegerLiteral *)stmt));
3448 case ZigClangStmt_ConditionalOperatorClass:
3449 return wrap_stmt(out_node, out_child_scope, scope,
3450 trans_conditional_operator(c, result_used, scope, (const ZigClangConditionalOperator *)stmt));
3451 case ZigClangStmt_BinaryOperatorClass:
3452 return wrap_stmt(out_node, out_child_scope, scope,
3453 trans_binary_operator(c, result_used, scope, (const ZigClangBinaryOperator *)stmt));
3454 case ZigClangStmt_CompoundAssignOperatorClass:
3455 return wrap_stmt(out_node, out_child_scope, scope,
3456 trans_compound_assign_operator(c, result_used, scope, (const ZigClangCompoundAssignOperator *)stmt));
3457 case ZigClangStmt_ImplicitCastExprClass:
3458 return wrap_stmt(out_node, out_child_scope, scope,
3459 trans_implicit_cast_expr(c, result_used, scope, (const ZigClangImplicitCastExpr *)stmt));
3460 case ZigClangStmt_DeclRefExprClass:
3461 return wrap_stmt(out_node, out_child_scope, scope,
3462 trans_decl_ref_expr(c, scope, (const ZigClangDeclRefExpr *)stmt, lrvalue));
3463 case ZigClangStmt_UnaryOperatorClass:
3464 return wrap_stmt(out_node, out_child_scope, scope,
3465 trans_unary_operator(c, result_used, scope, (const ZigClangUnaryOperator *)stmt));
3466 case ZigClangStmt_DeclStmtClass:
3467 return trans_local_declaration(c, scope, (const ZigClangDeclStmt *)stmt, out_node, out_child_scope);
3468 case ZigClangStmt_DoStmtClass:
3469 case ZigClangStmt_WhileStmtClass: {
3470 AstNode *while_node = sc == ZigClangStmt_DoStmtClass
3471 ? trans_do_loop(c, scope, (const ZigClangDoStmt *)stmt)
3472 : trans_while_loop(c, scope, (const ZigClangWhileStmt *)stmt);
3473
3474 if (while_node == nullptr)
3475 return ErrorUnexpected;
3476
3477 assert(while_node->type == NodeTypeWhileExpr);
3478 if (while_node->data.while_expr.body == nullptr)
3479 while_node->data.while_expr.body = trans_create_node(c, NodeTypeBlock);
3480
3481 return wrap_stmt(out_node, out_child_scope, scope, while_node);
3482 }
3483 case ZigClangStmt_IfStmtClass:
3484 return wrap_stmt(out_node, out_child_scope, scope,
3485 trans_if_statement(c, scope, (const ZigClangIfStmt *)stmt));
3486 case ZigClangStmt_CallExprClass:
3487 return wrap_stmt(out_node, out_child_scope, scope,
3488 trans_call_expr(c, result_used, scope, (const ZigClangCallExpr *)stmt));
3489 case ZigClangStmt_NullStmtClass:
3490 *out_node = trans_create_node(c, NodeTypeBlock);
3491 *out_child_scope = scope;
3492 return ErrorNone;
3493 case ZigClangStmt_MemberExprClass:
3494 return wrap_stmt(out_node, out_child_scope, scope,
3495 trans_member_expr(c, result_used, scope, (const ZigClangMemberExpr *)stmt));
3496 case ZigClangStmt_ArraySubscriptExprClass:
3497 return wrap_stmt(out_node, out_child_scope, scope,
3498 trans_array_subscript_expr(c, result_used, scope, (const ZigClangArraySubscriptExpr *)stmt));
3499 case ZigClangStmt_CStyleCastExprClass:
3500 return wrap_stmt(out_node, out_child_scope, scope,
3501 trans_c_style_cast_expr(c, result_used, scope, (const ZigClangCStyleCastExpr *)stmt, lrvalue));
3502 case ZigClangStmt_UnaryExprOrTypeTraitExprClass:
3503 return wrap_stmt(out_node, out_child_scope, scope,
3504 trans_unary_expr_or_type_trait_expr(c, result_used, scope, (const ZigClangUnaryExprOrTypeTraitExpr *)stmt));
3505 case ZigClangStmt_ForStmtClass: {
3506 AstNode *node = trans_for_loop(c, scope, (const ZigClangForStmt *)stmt);
3507 return wrap_stmt(out_node, out_child_scope, scope, node);
3508 }
3509 case ZigClangStmt_StringLiteralClass:
3510 return wrap_stmt(out_node, out_child_scope, scope,
3511 trans_string_literal(c, result_used, scope, (const ZigClangStringLiteral *)stmt));
3512 case ZigClangStmt_BreakStmtClass:
3513 return wrap_stmt(out_node, out_child_scope, scope,
3514 trans_break_stmt(c, scope, (const ZigClangBreakStmt *)stmt));
3515 case ZigClangStmt_ContinueStmtClass:
3516 return wrap_stmt(out_node, out_child_scope, scope,
3517 trans_continue_stmt(c, scope, (const ZigClangContinueStmt *)stmt));
3518 case ZigClangStmt_ParenExprClass:
3519 return wrap_stmt(out_node, out_child_scope, scope,
3520 trans_expr(c, result_used, scope,
3521 ZigClangParenExpr_getSubExpr((const ZigClangParenExpr *)stmt), lrvalue));
3522 case ZigClangStmt_SwitchStmtClass:
3523 return wrap_stmt(out_node, out_child_scope, scope,
3524 trans_switch_stmt(c, scope, (const ZigClangSwitchStmt *)stmt));
3525 case ZigClangStmt_CaseStmtClass:
3526 return trans_switch_case(c, scope, (const ZigClangCaseStmt *)stmt, out_node, out_child_scope);
3527 case ZigClangStmt_DefaultStmtClass:
3528 return trans_switch_default(c, scope, (const ZigClangDefaultStmt *)stmt, out_node, out_child_scope);
3529 case ZigClangStmt_ConstantExprClass:
3530 return wrap_stmt(out_node, out_child_scope, scope,
3531 trans_constant_expr(c, result_used, (const ZigClangConstantExpr *)stmt));
3532 case ZigClangStmt_PredefinedExprClass:
3533 return wrap_stmt(out_node, out_child_scope, scope,
3534 trans_predefined_expr(c, result_used, scope, (const ZigClangPredefinedExpr *)stmt));
3535 case ZigClangStmt_StmtExprClass:
3536 return wrap_stmt(out_node, out_child_scope, scope,
3537 trans_stmt_expr(c, result_used, scope, (const ZigClangStmtExpr *)stmt, out_node_scope));
3538 case ZigClangStmt_NoStmtClass:
3539 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoStmtClass");
3540 return ErrorUnexpected;
3541 case ZigClangStmt_GCCAsmStmtClass:
3542 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GCCAsmStmtClass");
3543 return ErrorUnexpected;
3544 case ZigClangStmt_MSAsmStmtClass:
3545 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSAsmStmtClass");
3546 return ErrorUnexpected;
3547 case ZigClangStmt_AttributedStmtClass:
3548 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AttributedStmtClass");
3549 return ErrorUnexpected;
3550 case ZigClangStmt_CXXCatchStmtClass:
3551 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXCatchStmtClass");
3552 return ErrorUnexpected;
3553 case ZigClangStmt_CXXForRangeStmtClass:
3554 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXForRangeStmtClass");
3555 return ErrorUnexpected;
3556 case ZigClangStmt_CXXTryStmtClass:
3557 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTryStmtClass");
3558 return ErrorUnexpected;
3559 case ZigClangStmt_CapturedStmtClass:
3560 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CapturedStmtClass");
3561 return ErrorUnexpected;
3562 case ZigClangStmt_CoreturnStmtClass:
3563 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoreturnStmtClass");
3564 return ErrorUnexpected;
3565 case ZigClangStmt_CoroutineBodyStmtClass:
3566 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoroutineBodyStmtClass");
3567 return ErrorUnexpected;
3568 case ZigClangStmt_BinaryConditionalOperatorClass:
3569 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BinaryConditionalOperatorClass");
3570 return ErrorUnexpected;
3571 case ZigClangStmt_AddrLabelExprClass:
3572 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AddrLabelExprClass");
3573 return ErrorUnexpected;
3574 case ZigClangStmt_ArrayInitIndexExprClass:
3575 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitIndexExprClass");
3576 return ErrorUnexpected;
3577 case ZigClangStmt_ArrayInitLoopExprClass:
3578 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayInitLoopExprClass");
3579 return ErrorUnexpected;
3580 case ZigClangStmt_ArrayTypeTraitExprClass:
3581 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ArrayTypeTraitExprClass");
3582 return ErrorUnexpected;
3583 case ZigClangStmt_AsTypeExprClass:
3584 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AsTypeExprClass");
3585 return ErrorUnexpected;
3586 case ZigClangStmt_AtomicExprClass:
3587 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C AtomicExprClass");
3588 return ErrorUnexpected;
3589 case ZigClangStmt_BlockExprClass:
3590 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BlockExprClass");
3591 return ErrorUnexpected;
3592 case ZigClangStmt_CXXBindTemporaryExprClass:
3593 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBindTemporaryExprClass");
3594 return ErrorUnexpected;
3595 case ZigClangStmt_CXXBoolLiteralExprClass:
3596 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXBoolLiteralExprClass");
3597 return ErrorUnexpected;
3598 case ZigClangStmt_CXXConstructExprClass:
3599 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstructExprClass");
3600 return ErrorUnexpected;
3601 case ZigClangStmt_CXXTemporaryObjectExprClass:
3602 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTemporaryObjectExprClass");
3603 return ErrorUnexpected;
3604 case ZigClangStmt_CXXDefaultArgExprClass:
3605 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultArgExprClass");
3606 return ErrorUnexpected;
3607 case ZigClangStmt_CXXDefaultInitExprClass:
3608 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDefaultInitExprClass");
3609 return ErrorUnexpected;
3610 case ZigClangStmt_CXXDeleteExprClass:
3611 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDeleteExprClass");
3612 return ErrorUnexpected;
3613 case ZigClangStmt_CXXDependentScopeMemberExprClass:
3614 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDependentScopeMemberExprClass");
3615 return ErrorUnexpected;
3616 case ZigClangStmt_CXXFoldExprClass:
3617 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFoldExprClass");
3618 return ErrorUnexpected;
3619 case ZigClangStmt_CXXInheritedCtorInitExprClass:
3620 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXInheritedCtorInitExprClass");
3621 return ErrorUnexpected;
3622 case ZigClangStmt_CXXNewExprClass:
3623 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNewExprClass");
3624 return ErrorUnexpected;
3625 case ZigClangStmt_CXXNoexceptExprClass:
3626 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNoexceptExprClass");
3627 return ErrorUnexpected;
3628 case ZigClangStmt_CXXNullPtrLiteralExprClass:
3629 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXNullPtrLiteralExprClass");
3630 return ErrorUnexpected;
3631 case ZigClangStmt_CXXPseudoDestructorExprClass:
3632 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXPseudoDestructorExprClass");
3633 return ErrorUnexpected;
3634 case ZigClangStmt_CXXScalarValueInitExprClass:
3635 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXScalarValueInitExprClass");
3636 return ErrorUnexpected;
3637 case ZigClangStmt_CXXStdInitializerListExprClass:
3638 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStdInitializerListExprClass");
3639 return ErrorUnexpected;
3640 case ZigClangStmt_CXXThisExprClass:
3641 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThisExprClass");
3642 return ErrorUnexpected;
3643 case ZigClangStmt_CXXThrowExprClass:
3644 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXThrowExprClass");
3645 return ErrorUnexpected;
3646 case ZigClangStmt_CXXTypeidExprClass:
3647 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXTypeidExprClass");
3648 return ErrorUnexpected;
3649 case ZigClangStmt_CXXUnresolvedConstructExprClass:
3650 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUnresolvedConstructExprClass");
3651 return ErrorUnexpected;
3652 case ZigClangStmt_CXXUuidofExprClass:
3653 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXUuidofExprClass");
3654 return ErrorUnexpected;
3655 case ZigClangStmt_CUDAKernelCallExprClass:
3656 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CUDAKernelCallExprClass");
3657 return ErrorUnexpected;
3658 case ZigClangStmt_CXXMemberCallExprClass:
3659 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXMemberCallExprClass");
3660 return ErrorUnexpected;
3661 case ZigClangStmt_CXXOperatorCallExprClass:
3662 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXOperatorCallExprClass");
3663 return ErrorUnexpected;
3664 case ZigClangStmt_UserDefinedLiteralClass:
3665 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UserDefinedLiteralClass");
3666 return ErrorUnexpected;
3667 case ZigClangStmt_CXXFunctionalCastExprClass:
3668 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXFunctionalCastExprClass");
3669 return ErrorUnexpected;
3670 case ZigClangStmt_CXXConstCastExprClass:
3671 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXConstCastExprClass");
3672 return ErrorUnexpected;
3673 case ZigClangStmt_CXXDynamicCastExprClass:
3674 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXDynamicCastExprClass");
3675 return ErrorUnexpected;
3676 case ZigClangStmt_CXXReinterpretCastExprClass:
3677 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXReinterpretCastExprClass");
3678 return ErrorUnexpected;
3679 case ZigClangStmt_CXXStaticCastExprClass:
3680 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CXXStaticCastExprClass");
3681 return ErrorUnexpected;
3682 case ZigClangStmt_ObjCBridgedCastExprClass:
3683 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBridgedCastExprClass");
3684 return ErrorUnexpected;
3685 case ZigClangStmt_CharacterLiteralClass:
3686 return wrap_stmt(out_node, out_child_scope, scope,
3687 trans_character_literal(c, result_used, (const ZigClangCharacterLiteral *)stmt));
3688 return ErrorUnexpected;
3689 case ZigClangStmt_ChooseExprClass:
3690 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ChooseExprClass");
3691 return ErrorUnexpected;
3692 case ZigClangStmt_CompoundLiteralExprClass:
3693 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CompoundLiteralExprClass");
3694 return ErrorUnexpected;
3695 case ZigClangStmt_ConvertVectorExprClass:
3696 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ConvertVectorExprClass");
3697 return ErrorUnexpected;
3698 case ZigClangStmt_CoawaitExprClass:
3699 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoawaitExprClass");
3700 return ErrorUnexpected;
3701 case ZigClangStmt_CoyieldExprClass:
3702 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C CoyieldExprClass");
3703 return ErrorUnexpected;
3704 case ZigClangStmt_DependentCoawaitExprClass:
3705 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentCoawaitExprClass");
3706 return ErrorUnexpected;
3707 case ZigClangStmt_DependentScopeDeclRefExprClass:
3708 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DependentScopeDeclRefExprClass");
3709 return ErrorUnexpected;
3710 case ZigClangStmt_DesignatedInitExprClass:
3711 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitExprClass");
3712 return ErrorUnexpected;
3713 case ZigClangStmt_DesignatedInitUpdateExprClass:
3714 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C DesignatedInitUpdateExprClass");
3715 return ErrorUnexpected;
3716 case ZigClangStmt_ExpressionTraitExprClass:
3717 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExpressionTraitExprClass");
3718 return ErrorUnexpected;
3719 case ZigClangStmt_ExtVectorElementExprClass:
3720 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExtVectorElementExprClass");
3721 return ErrorUnexpected;
3722 case ZigClangStmt_FixedPointLiteralClass:
3723 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FixedPointLiteralClass");
3724 return ErrorUnexpected;
3725 case ZigClangStmt_FloatingLiteralClass:
3726 return wrap_stmt(out_node, out_child_scope, scope,
3727 trans_floating_literal(c, result_used, (const ZigClangFloatingLiteral *)stmt));
3728 case ZigClangStmt_ExprWithCleanupsClass:
3729 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ExprWithCleanupsClass");
3730 return ErrorUnexpected;
3731 case ZigClangStmt_FunctionParmPackExprClass:
3732 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C FunctionParmPackExprClass");
3733 return ErrorUnexpected;
3734 case ZigClangStmt_GNUNullExprClass:
3735 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GNUNullExprClass");
3736 return ErrorUnexpected;
3737 case ZigClangStmt_GenericSelectionExprClass:
3738 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GenericSelectionExprClass");
3739 return ErrorUnexpected;
3740 case ZigClangStmt_ImaginaryLiteralClass:
3741 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImaginaryLiteralClass");
3742 return ErrorUnexpected;
3743 case ZigClangStmt_ImplicitValueInitExprClass:
3744 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ImplicitValueInitExprClass");
3745 return ErrorUnexpected;
3746 case ZigClangStmt_InitListExprClass:
3747 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C InitListExprClass");
3748 return ErrorUnexpected;
3749 case ZigClangStmt_LambdaExprClass:
3750 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LambdaExprClass");
3751 return ErrorUnexpected;
3752 case ZigClangStmt_MSPropertyRefExprClass:
3753 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertyRefExprClass");
3754 return ErrorUnexpected;
3755 case ZigClangStmt_MSPropertySubscriptExprClass:
3756 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSPropertySubscriptExprClass");
3757 return ErrorUnexpected;
3758 case ZigClangStmt_MaterializeTemporaryExprClass:
3759 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MaterializeTemporaryExprClass");
3760 return ErrorUnexpected;
3761 case ZigClangStmt_NoInitExprClass:
3762 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C NoInitExprClass");
3763 return ErrorUnexpected;
3764 case ZigClangStmt_OMPArraySectionExprClass:
3765 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPArraySectionExprClass");
3766 return ErrorUnexpected;
3767 case ZigClangStmt_ObjCArrayLiteralClass:
3768 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCArrayLiteralClass");
3769 return ErrorUnexpected;
3770 case ZigClangStmt_ObjCAvailabilityCheckExprClass:
3771 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAvailabilityCheckExprClass");
3772 return ErrorUnexpected;
3773 case ZigClangStmt_ObjCBoolLiteralExprClass:
3774 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoolLiteralExprClass");
3775 return ErrorUnexpected;
3776 case ZigClangStmt_ObjCBoxedExprClass:
3777 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCBoxedExprClass");
3778 return ErrorUnexpected;
3779 case ZigClangStmt_ObjCDictionaryLiteralClass:
3780 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCDictionaryLiteralClass");
3781 return ErrorUnexpected;
3782 case ZigClangStmt_ObjCEncodeExprClass:
3783 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCEncodeExprClass");
3784 return ErrorUnexpected;
3785 case ZigClangStmt_ObjCIndirectCopyRestoreExprClass:
3786 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIndirectCopyRestoreExprClass");
3787 return ErrorUnexpected;
3788 case ZigClangStmt_ObjCIsaExprClass:
3789 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIsaExprClass");
3790 return ErrorUnexpected;
3791 case ZigClangStmt_ObjCIvarRefExprClass:
3792 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCIvarRefExprClass");
3793 return ErrorUnexpected;
3794 case ZigClangStmt_ObjCMessageExprClass:
3795 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCMessageExprClass");
3796 return ErrorUnexpected;
3797 case ZigClangStmt_ObjCPropertyRefExprClass:
3798 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCPropertyRefExprClass");
3799 return ErrorUnexpected;
3800 case ZigClangStmt_ObjCProtocolExprClass:
3801 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCProtocolExprClass");
3802 return ErrorUnexpected;
3803 case ZigClangStmt_ObjCSelectorExprClass:
3804 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSelectorExprClass");
3805 return ErrorUnexpected;
3806 case ZigClangStmt_ObjCStringLiteralClass:
3807 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCStringLiteralClass");
3808 return ErrorUnexpected;
3809 case ZigClangStmt_ObjCSubscriptRefExprClass:
3810 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCSubscriptRefExprClass");
3811 return ErrorUnexpected;
3812 case ZigClangStmt_OffsetOfExprClass:
3813 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OffsetOfExprClass");
3814 return ErrorUnexpected;
3815 case ZigClangStmt_OpaqueValueExprClass:
3816 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OpaqueValueExprClass");
3817 return ErrorUnexpected;
3818 case ZigClangStmt_UnresolvedLookupExprClass:
3819 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedLookupExprClass");
3820 return ErrorUnexpected;
3821 case ZigClangStmt_UnresolvedMemberExprClass:
3822 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C UnresolvedMemberExprClass");
3823 return ErrorUnexpected;
3824 case ZigClangStmt_PackExpansionExprClass:
3825 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PackExpansionExprClass");
3826 return ErrorUnexpected;
3827 case ZigClangStmt_ParenListExprClass:
3828 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ParenListExprClass");
3829 return ErrorUnexpected;
3830 case ZigClangStmt_PseudoObjectExprClass:
3831 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C PseudoObjectExprClass");
3832 return ErrorUnexpected;
3833 case ZigClangStmt_ShuffleVectorExprClass:
3834 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ShuffleVectorExprClass");
3835 return ErrorUnexpected;
3836 case ZigClangStmt_SizeOfPackExprClass:
3837 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SizeOfPackExprClass");
3838 return ErrorUnexpected;
3839 case ZigClangStmt_SubstNonTypeTemplateParmExprClass:
3840 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmExprClass");
3841 return ErrorUnexpected;
3842 case ZigClangStmt_SubstNonTypeTemplateParmPackExprClass:
3843 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
3844 return ErrorUnexpected;
3845 case ZigClangStmt_TypeTraitExprClass:
3846 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypeTraitExprClass");
3847 return ErrorUnexpected;
3848 case ZigClangStmt_TypoExprClass:
3849 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C TypoExprClass");
3850 return ErrorUnexpected;
3851 case ZigClangStmt_VAArgExprClass:
3852 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C VAArgExprClass");
3853 return ErrorUnexpected;
3854 case ZigClangStmt_GotoStmtClass:
3855 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C GotoStmtClass");
3856 return ErrorUnexpected;
3857 case ZigClangStmt_IndirectGotoStmtClass:
3858 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C IndirectGotoStmtClass");
3859 return ErrorUnexpected;
3860 case ZigClangStmt_LabelStmtClass:
3861 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C LabelStmtClass");
3862 return ErrorUnexpected;
3863 case ZigClangStmt_MSDependentExistsStmtClass:
3864 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C MSDependentExistsStmtClass");
3865 return ErrorUnexpected;
3866 case ZigClangStmt_OMPAtomicDirectiveClass:
3867 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPAtomicDirectiveClass");
3868 return ErrorUnexpected;
3869 case ZigClangStmt_OMPBarrierDirectiveClass:
3870 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPBarrierDirectiveClass");
3871 return ErrorUnexpected;
3872 case ZigClangStmt_OMPCancelDirectiveClass:
3873 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancelDirectiveClass");
3874 return ErrorUnexpected;
3875 case ZigClangStmt_OMPCancellationPointDirectiveClass:
3876 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCancellationPointDirectiveClass");
3877 return ErrorUnexpected;
3878 case ZigClangStmt_OMPCriticalDirectiveClass:
3879 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPCriticalDirectiveClass");
3880 return ErrorUnexpected;
3881 case ZigClangStmt_OMPFlushDirectiveClass:
3882 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPFlushDirectiveClass");
3883 return ErrorUnexpected;
3884 case ZigClangStmt_OMPDistributeDirectiveClass:
3885 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeDirectiveClass");
3886 return ErrorUnexpected;
3887 case ZigClangStmt_OMPDistributeParallelForDirectiveClass:
3888 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForDirectiveClass");
3889 return ErrorUnexpected;
3890 case ZigClangStmt_OMPDistributeParallelForSimdDirectiveClass:
3891 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
3892 return ErrorUnexpected;
3893 case ZigClangStmt_OMPDistributeSimdDirectiveClass:
3894 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPDistributeSimdDirectiveClass");
3895 return ErrorUnexpected;
3896 case ZigClangStmt_OMPForDirectiveClass:
3897 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForDirectiveClass");
3898 return ErrorUnexpected;
3899 case ZigClangStmt_OMPForSimdDirectiveClass:
3900 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPForSimdDirectiveClass");
3901 return ErrorUnexpected;
3902 case ZigClangStmt_OMPParallelForDirectiveClass:
3903 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForDirectiveClass");
3904 return ErrorUnexpected;
3905 case ZigClangStmt_OMPParallelForSimdDirectiveClass:
3906 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelForSimdDirectiveClass");
3907 return ErrorUnexpected;
3908 case ZigClangStmt_OMPSimdDirectiveClass:
3909 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSimdDirectiveClass");
3910 return ErrorUnexpected;
3911 case ZigClangStmt_OMPTargetParallelForSimdDirectiveClass:
3912 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
3913 return ErrorUnexpected;
3914 case ZigClangStmt_OMPTargetSimdDirectiveClass:
3915 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetSimdDirectiveClass");
3916 return ErrorUnexpected;
3917 case ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass:
3918 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
3919 return ErrorUnexpected;
3920 case ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass:
3921 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
3922 return ErrorUnexpected;
3923 case ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
3924 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
3925 return ErrorUnexpected;
3926 case ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass:
3927 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
3928 return ErrorUnexpected;
3929 case ZigClangStmt_OMPTaskLoopDirectiveClass:
3930 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopDirectiveClass");
3931 return ErrorUnexpected;
3932 case ZigClangStmt_OMPTaskLoopSimdDirectiveClass:
3933 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskLoopSimdDirectiveClass");
3934 return ErrorUnexpected;
3935 case ZigClangStmt_OMPTeamsDistributeDirectiveClass:
3936 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeDirectiveClass");
3937 return ErrorUnexpected;
3938 case ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass:
3939 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
3940 return ErrorUnexpected;
3941 case ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass:
3942 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
3943 return ErrorUnexpected;
3944 case ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass:
3945 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
3946 return ErrorUnexpected;
3947 case ZigClangStmt_OMPMasterDirectiveClass:
3948 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPMasterDirectiveClass");
3949 return ErrorUnexpected;
3950 case ZigClangStmt_OMPOrderedDirectiveClass:
3951 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPOrderedDirectiveClass");
3952 return ErrorUnexpected;
3953 case ZigClangStmt_OMPParallelDirectiveClass:
3954 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelDirectiveClass");
3955 return ErrorUnexpected;
3956 case ZigClangStmt_OMPParallelSectionsDirectiveClass:
3957 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPParallelSectionsDirectiveClass");
3958 return ErrorUnexpected;
3959 case ZigClangStmt_OMPSectionDirectiveClass:
3960 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionDirectiveClass");
3961 return ErrorUnexpected;
3962 case ZigClangStmt_OMPSectionsDirectiveClass:
3963 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSectionsDirectiveClass");
3964 return ErrorUnexpected;
3965 case ZigClangStmt_OMPSingleDirectiveClass:
3966 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPSingleDirectiveClass");
3967 return ErrorUnexpected;
3968 case ZigClangStmt_OMPTargetDataDirectiveClass:
3969 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDataDirectiveClass");
3970 return ErrorUnexpected;
3971 case ZigClangStmt_OMPTargetDirectiveClass:
3972 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetDirectiveClass");
3973 return ErrorUnexpected;
3974 case ZigClangStmt_OMPTargetEnterDataDirectiveClass:
3975 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetEnterDataDirectiveClass");
3976 return ErrorUnexpected;
3977 case ZigClangStmt_OMPTargetExitDataDirectiveClass:
3978 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetExitDataDirectiveClass");
3979 return ErrorUnexpected;
3980 case ZigClangStmt_OMPTargetParallelDirectiveClass:
3981 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelDirectiveClass");
3982 return ErrorUnexpected;
3983 case ZigClangStmt_OMPTargetParallelForDirectiveClass:
3984 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetParallelForDirectiveClass");
3985 return ErrorUnexpected;
3986 case ZigClangStmt_OMPTargetTeamsDirectiveClass:
3987 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetTeamsDirectiveClass");
3988 return ErrorUnexpected;
3989 case ZigClangStmt_OMPTargetUpdateDirectiveClass:
3990 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTargetUpdateDirectiveClass");
3991 return ErrorUnexpected;
3992 case ZigClangStmt_OMPTaskDirectiveClass:
3993 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskDirectiveClass");
3994 return ErrorUnexpected;
3995 case ZigClangStmt_OMPTaskgroupDirectiveClass:
3996 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskgroupDirectiveClass");
3997 return ErrorUnexpected;
3998 case ZigClangStmt_OMPTaskwaitDirectiveClass:
3999 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskwaitDirectiveClass");
4000 return ErrorUnexpected;
4001 case ZigClangStmt_OMPTaskyieldDirectiveClass:
4002 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTaskyieldDirectiveClass");
4003 return ErrorUnexpected;
4004 case ZigClangStmt_OMPTeamsDirectiveClass:
4005 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C OMPTeamsDirectiveClass");
4006 return ErrorUnexpected;
4007 case ZigClangStmt_ObjCAtCatchStmtClass:
4008 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtCatchStmtClass");
4009 return ErrorUnexpected;
4010 case ZigClangStmt_ObjCAtFinallyStmtClass:
4011 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtFinallyStmtClass");
4012 return ErrorUnexpected;
4013 case ZigClangStmt_ObjCAtSynchronizedStmtClass:
4014 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtSynchronizedStmtClass");
4015 return ErrorUnexpected;
4016 case ZigClangStmt_ObjCAtThrowStmtClass:
4017 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtThrowStmtClass");
4018 return ErrorUnexpected;
4019 case ZigClangStmt_ObjCAtTryStmtClass:
4020 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAtTryStmtClass");
4021 return ErrorUnexpected;
4022 case ZigClangStmt_ObjCAutoreleasePoolStmtClass:
4023 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCAutoreleasePoolStmtClass");
4024 return ErrorUnexpected;
4025 case ZigClangStmt_ObjCForCollectionStmtClass:
4026 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C ObjCForCollectionStmtClass");
4027 return ErrorUnexpected;
4028 case ZigClangStmt_SEHExceptStmtClass:
4029 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHExceptStmtClass");
4030 return ErrorUnexpected;
4031 case ZigClangStmt_SEHFinallyStmtClass:
4032 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHFinallyStmtClass");
4033 return ErrorUnexpected;
4034 case ZigClangStmt_SEHLeaveStmtClass:
4035 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHLeaveStmtClass");
4036 return ErrorUnexpected;
4037 case ZigClangStmt_SEHTryStmtClass:
4038 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SEHTryStmtClass");
4039 return ErrorUnexpected;
4040 case ZigClangStmt_BuiltinBitCastExprClass:
4041 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C BuiltinBitCastExprClass");
4042 return ErrorUnexpected;
4043 case ZigClangStmt_SourceLocExprClass:
4044 emit_warning(c, ZigClangStmt_getBeginLoc(stmt), "TODO handle C SourceLocExprClass");
4045 return ErrorUnexpected;
4046 }
4047 zig_unreachable();
4048}
4049
4050// Returns null if there was an error
4051static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const ZigClangExpr *expr,
4052 TransLRValue lrval)
4053{
4054 AstNode *result_node;
4055 TransScope *result_scope;
4056 if (trans_stmt_extra(c, scope, (const ZigClangStmt *)expr, result_used, lrval, &result_node, &result_scope, nullptr)) {
4057 return nullptr;
4058 }
4059 return result_node;
4060}
4061
4062// Statements have no result and no concept of L or R value.
4063// Returns child scope, or null if there was an error
4064static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt *stmt, AstNode **out_node) {
4065 TransScope *child_scope;
4066 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
4067 return nullptr;
4068 }
4069 return child_scope;
4070}
4071
4072static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
4073 Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl));
4074
4075 if (get_global(c, fn_name)) {
4076 // we already saw this function
4077 return;
4078 }
4079
4080 AstNode *proto_node = trans_qual_type(c, ZigClangFunctionDecl_getType(fn_decl),
4081 ZigClangFunctionDecl_getLocation(fn_decl));
4082 if (proto_node == nullptr) {
4083 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl),
4084 "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
4085 return;
4086 }
4087
4088 proto_node->data.fn_proto.name = fn_name;
4089 proto_node->data.fn_proto.is_extern = !ZigClangFunctionDecl_hasBody(fn_decl);
4090
4091 ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
4092 if (sc == ZigClangStorageClass_None) {
4093 proto_node->data.fn_proto.visib_mod = VisibModPub;
4094 proto_node->data.fn_proto.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
4095 } else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
4096 proto_node->data.fn_proto.visib_mod = VisibModPub;
4097 } else if (sc == ZigClangStorageClass_PrivateExtern) {
4098 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
4099 return;
4100 } else {
4101 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: unknown");
4102 return;
4103 }
4104
4105 TransScope *scope = &c->global_scope->base;
4106
4107 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
4108 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
4109 const ZigClangParmVarDecl *param = ZigClangFunctionDecl_getParamDecl(fn_decl, i);
4110 const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param);
4111
4112 Buf *proto_param_name;
4113 if (strlen(name) != 0) {
4114 proto_param_name = buf_create_from_str(name);
4115 } else {
4116 proto_param_name = param_node->data.param_decl.name;
4117 if (proto_param_name == nullptr) {
4118 proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
4119 }
4120 }
4121
4122 TransScopeVar *scope_var = trans_scope_var_create(c, scope, proto_param_name);
4123 scope = &scope_var->base;
4124
4125 param_node->data.param_decl.name = scope_var->zig_name;
4126 }
4127
4128 if (!ZigClangFunctionDecl_hasBody(fn_decl)) {
4129 // just a prototype
4130 add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
4131 return;
4132 }
4133
4134 // actual function definition with body
4135 c->ptr_params.clear();
4136 const ZigClangStmt *body = ZigClangFunctionDecl_getBody(fn_decl);
4137 AstNode *actual_body_node;
4138 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
4139 if (result_scope == nullptr) {
4140 emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unable to translate function");
4141 return;
4142 }
4143 assert(actual_body_node != nullptr);
4144 assert(actual_body_node->type == NodeTypeBlock);
4145
4146 // it worked
4147
4148 AstNode *body_node_with_param_inits = trans_create_node(c, NodeTypeBlock);
4149
4150 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
4151 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
4152 Buf *good_name = param_node->data.param_decl.name;
4153
4154 if (c->ptr_params.maybe_get(good_name) != nullptr) {
4155 // TODO: avoid name collisions
4156 Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name));
4157 param_node->data.param_decl.name = mangled_name;
4158
4159 // var c_name = _mangled_name;
4160 AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name));
4161
4162 body_node_with_param_inits->data.block.statements.append(parameter_init);
4163 }
4164 }
4165
4166 for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) {
4167 body_node_with_param_inits->data.block.statements.append(actual_body_node->data.block.statements.at(i));
4168 }
4169
4170 AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef);
4171 fn_def_node->data.fn_def.fn_proto = proto_node;
4172 fn_def_node->data.fn_def.body = body_node_with_param_inits;
4173
4174 proto_node->data.fn_proto.fn_def_node = fn_def_node;
4175 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
4176}
4177
4178static AstNode *resolve_typdef_as_builtin(Context *c, const ZigClangTypedefNameDecl *typedef_decl, const char *primitive_name) {
4179 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
4180 c->decl_table.put(typedef_decl, node);
4181 return node;
4182}
4183
4184static AstNode *resolve_typedef_decl(Context *c, const ZigClangTypedefNameDecl *typedef_decl) {
4185 auto existing_entry = c->decl_table.maybe_get((void*)ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl));
4186 if (existing_entry) {
4187 return existing_entry->value;
4188 }
4189
4190 ZigClangQualType child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
4191 Buf *type_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)typedef_decl));
4192
4193 if (buf_eql_str(type_name, "uint8_t")) {
4194 return resolve_typdef_as_builtin(c, typedef_decl, "u8");
4195 } else if (buf_eql_str(type_name, "int8_t")) {
4196 return resolve_typdef_as_builtin(c, typedef_decl, "i8");
4197 } else if (buf_eql_str(type_name, "uint16_t")) {
4198 return resolve_typdef_as_builtin(c, typedef_decl, "u16");
4199 } else if (buf_eql_str(type_name, "int16_t")) {
4200 return resolve_typdef_as_builtin(c, typedef_decl, "i16");
4201 } else if (buf_eql_str(type_name, "uint32_t")) {
4202 return resolve_typdef_as_builtin(c, typedef_decl, "u32");
4203 } else if (buf_eql_str(type_name, "int32_t")) {
4204 return resolve_typdef_as_builtin(c, typedef_decl, "i32");
4205 } else if (buf_eql_str(type_name, "uint64_t")) {
4206 return resolve_typdef_as_builtin(c, typedef_decl, "u64");
4207 } else if (buf_eql_str(type_name, "int64_t")) {
4208 return resolve_typdef_as_builtin(c, typedef_decl, "i64");
4209 } else if (buf_eql_str(type_name, "intptr_t")) {
4210 return resolve_typdef_as_builtin(c, typedef_decl, "isize");
4211 } else if (buf_eql_str(type_name, "uintptr_t")) {
4212 return resolve_typdef_as_builtin(c, typedef_decl, "usize");
4213 } else if (buf_eql_str(type_name, "ssize_t")) {
4214 return resolve_typdef_as_builtin(c, typedef_decl, "isize");
4215 } else if (buf_eql_str(type_name, "size_t")) {
4216 return resolve_typdef_as_builtin(c, typedef_decl, "usize");
4217 }
4218
4219 // if the underlying type is anonymous, we can special case it to just
4220 // use the name of this typedef
4221 // TODO
4222
4223 // trans_qual_type here might cause us to look at this typedef again so we put the item in the map first
4224 AstNode *symbol_node = trans_create_node_symbol(c, type_name);
4225 c->decl_table.put(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl), symbol_node);
4226
4227 AstNode *type_node = trans_qual_type(c, child_qt, ZigClangTypedefNameDecl_getLocation(typedef_decl));
4228 if (type_node == nullptr) {
4229 emit_warning(c, ZigClangTypedefNameDecl_getLocation(typedef_decl),
4230 "typedef %s - unresolved child type", buf_ptr(type_name));
4231 c->decl_table.put(typedef_decl, nullptr);
4232 // TODO add global var with type_name equal to @compileError("unable to resolve C type")
4233 return nullptr;
4234 }
4235 add_global_var(c, type_name, type_node);
4236
4237 return symbol_node;
4238}
4239
4240struct AstNode *demote_enum_to_opaque(Context *c, const ZigClangEnumDecl *enum_decl, Buf *full_type_name,
4241 Buf *bare_name)
4242{
4243 AstNode *opaque_node = trans_create_node_opaque(c);
4244 if (full_type_name == nullptr) {
4245 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), opaque_node);
4246 return opaque_node;
4247 }
4248 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
4249 add_global_weak_alias(c, bare_name, full_type_name);
4250 add_global_var(c, full_type_name, opaque_node);
4251 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), symbol_node);
4252 return symbol_node;
4253}
4254
4255static AstNode *resolve_enum_decl(Context *c, const ZigClangEnumDecl *enum_decl) {
4256 auto existing_entry = c->decl_table.maybe_get(ZigClangEnumDecl_getCanonicalDecl(enum_decl));
4257 if (existing_entry) {
4258 return existing_entry->value;
4259 }
4260
4261 const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_decl);
4262 bool is_anonymous = (raw_name[0] == 0);
4263 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
4264 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
4265
4266 const ZigClangEnumDecl *enum_def = ZigClangEnumDecl_getDefinition(enum_decl);
4267 if (!enum_def) {
4268 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
4269 }
4270
4271
4272 bool pure_enum = true;
4273 uint32_t field_count = 0;
4274 for (ZigClangEnumDecl_enumerator_iterator it = ZigClangEnumDecl_enumerator_begin(enum_def),
4275 it_end = ZigClangEnumDecl_enumerator_end(enum_def);
4276 ZigClangEnumDecl_enumerator_iterator_neq(it, it_end);
4277 it = ZigClangEnumDecl_enumerator_iterator_next(it), field_count += 1)
4278 {
4279 const ZigClangEnumConstantDecl *enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
4280 if (ZigClangEnumConstantDecl_getInitExpr(enum_const)) {
4281 pure_enum = false;
4282 }
4283 }
4284 AstNode *tag_int_type = trans_qual_type(c, ZigClangEnumDecl_getIntegerType(enum_decl),
4285 ZigClangEnumDecl_getLocation(enum_decl));
4286 assert(tag_int_type);
4287
4288 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
4289 enum_node->data.container_decl.kind = ContainerKindEnum;
4290 enum_node->data.container_decl.layout = ContainerLayoutExtern;
4291 // TODO only emit this tag type if the enum tag type is not the default.
4292 // I don't know what the default is, need to figure out how clang is deciding.
4293 // it appears to at least be different across gcc/msvc
4294 if (!c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeUInt) &&
4295 !c_is_builtin_type(c, ZigClangEnumDecl_getIntegerType(enum_decl), ZigClangBuiltinTypeInt))
4296 {
4297 enum_node->data.container_decl.init_arg_expr = tag_int_type;
4298 }
4299 enum_node->data.container_decl.fields.resize(field_count);
4300 uint32_t i = 0;
4301 for (ZigClangEnumDecl_enumerator_iterator it = ZigClangEnumDecl_enumerator_begin(enum_def),
4302 it_end = ZigClangEnumDecl_enumerator_end(enum_def);
4303 ZigClangEnumDecl_enumerator_iterator_neq(it, it_end);
4304 it = ZigClangEnumDecl_enumerator_iterator_next(it), i += 1)
4305 {
4306 const ZigClangEnumConstantDecl *enum_const = ZigClangEnumDecl_enumerator_iterator_deref(it);
4307
4308 Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const));
4309 Buf *field_name;
4310 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
4311 field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
4312 } else {
4313 field_name = enum_val_name;
4314 }
4315
4316 AstNode *int_node = pure_enum && !is_anonymous ?
4317 nullptr : trans_create_node_apint(c, ZigClangEnumConstantDecl_getInitVal(enum_const));
4318 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
4319 field_node->data.struct_field.name = field_name;
4320 field_node->data.struct_field.type = nullptr;
4321 field_node->data.struct_field.value = int_node;
4322 enum_node->data.container_decl.fields.items[i] = field_node;
4323
4324 // in C each enum value is in the global namespace. so we put them there too.
4325 // at this point we can rely on the enum emitting successfully
4326 if (is_anonymous) {
4327 Buf *enum_val_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)enum_const));
4328 add_global_var(c, enum_val_name, int_node);
4329 } else {
4330 AstNode *field_access_node = trans_create_node_field_access(c,
4331 trans_create_node_symbol(c, full_type_name), field_name);
4332 add_global_var(c, enum_val_name, field_access_node);
4333 }
4334 }
4335
4336 if (is_anonymous) {
4337 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), enum_node);
4338 return enum_node;
4339 } else {
4340 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
4341 add_global_weak_alias(c, bare_name, full_type_name);
4342 add_global_var(c, full_type_name, enum_node);
4343 c->decl_table.put(ZigClangEnumDecl_getCanonicalDecl(enum_decl), symbol_node);
4344 return enum_node;
4345 }
4346}
4347
4348static AstNode *demote_struct_to_opaque(Context *c, const ZigClangRecordDecl *record_decl,
4349 Buf *full_type_name, Buf *bare_name)
4350{
4351 AstNode *opaque_node = trans_create_node_opaque(c);
4352 if (full_type_name == nullptr) {
4353 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), opaque_node);
4354 return opaque_node;
4355 }
4356 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
4357 add_global_weak_alias(c, bare_name, full_type_name);
4358 add_global_var(c, full_type_name, opaque_node);
4359 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), symbol_node);
4360 return symbol_node;
4361}
4362
4363static AstNode *resolve_record_decl(Context *c, const ZigClangRecordDecl *record_decl) {
4364 auto existing_entry = c->decl_table.maybe_get(ZigClangRecordDecl_getCanonicalDecl(record_decl));
4365 if (existing_entry) {
4366 return existing_entry->value;
4367 }
4368
4369 const char *raw_name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)record_decl);
4370 const char *container_kind_name;
4371 ContainerKind container_kind;
4372 if (ZigClangRecordDecl_isUnion(record_decl)) {
4373 container_kind_name = "union";
4374 container_kind = ContainerKindUnion;
4375 } else if (ZigClangRecordDecl_isStruct(record_decl)) {
4376 container_kind_name = "struct";
4377 container_kind = ContainerKindStruct;
4378 } else {
4379 emit_warning(c, ZigClangRecordDecl_getLocation(record_decl),
4380 "skipping record %s, not a struct or union", raw_name);
4381 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), nullptr);
4382 return nullptr;
4383 }
4384
4385 bool is_anonymous = ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl) || raw_name[0] == 0;
4386 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
4387 Buf *full_type_name = (bare_name == nullptr) ?
4388 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
4389
4390 const ZigClangRecordDecl *record_def = ZigClangRecordDecl_getDefinition(record_decl);
4391 if (record_def == nullptr) {
4392 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
4393 }
4394
4395 // count fields and validate
4396 uint32_t field_count = 0;
4397 for (ZigClangRecordDecl_field_iterator it = ZigClangRecordDecl_field_begin(record_def),
4398 it_end = ZigClangRecordDecl_field_end(record_def);
4399 ZigClangRecordDecl_field_iterator_neq(it, it_end);
4400 it = ZigClangRecordDecl_field_iterator_next(it), field_count += 1)
4401 {
4402 const ZigClangFieldDecl *field_decl = ZigClangRecordDecl_field_iterator_deref(it);
4403
4404 if (ZigClangFieldDecl_isBitField(field_decl)) {
4405 emit_warning(c, ZigClangFieldDecl_getLocation(field_decl),
4406 "%s %s demoted to opaque type - has bitfield", container_kind_name,
4407 is_anonymous ? "(anon)" : buf_ptr(bare_name));
4408 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
4409 }
4410 }
4411
4412 AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl);
4413 struct_node->data.container_decl.kind = container_kind;
4414 struct_node->data.container_decl.layout = ContainerLayoutExtern;
4415
4416 // TODO handle attribute packed
4417
4418 struct_node->data.container_decl.fields.resize(field_count);
4419
4420 // must be before fields in case a circular reference happens
4421 if (is_anonymous) {
4422 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), struct_node);
4423 } else {
4424 c->decl_table.put(ZigClangRecordDecl_getCanonicalDecl(record_decl), trans_create_node_symbol(c, full_type_name));
4425 }
4426
4427 uint32_t i = 0;
4428 for (ZigClangRecordDecl_field_iterator it = ZigClangRecordDecl_field_begin(record_def),
4429 it_end = ZigClangRecordDecl_field_end(record_def);
4430 ZigClangRecordDecl_field_iterator_neq(it, it_end);
4431 it = ZigClangRecordDecl_field_iterator_next(it), i += 1)
4432 {
4433 const ZigClangFieldDecl *field_decl = ZigClangRecordDecl_field_iterator_deref(it);
4434
4435 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
4436 field_node->data.struct_field.name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)field_decl));
4437 field_node->data.struct_field.type = trans_qual_type(c, ZigClangFieldDecl_getType(field_decl),
4438 ZigClangFieldDecl_getLocation(field_decl));
4439
4440 if (field_node->data.struct_field.type == nullptr) {
4441 emit_warning(c, ZigClangFieldDecl_getLocation(field_decl),
4442 "%s %s demoted to opaque type - unresolved type",
4443 container_kind_name,
4444 is_anonymous ? "(anon)" : buf_ptr(bare_name));
4445
4446 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
4447 }
4448
4449 struct_node->data.container_decl.fields.items[i] = field_node;
4450 }
4451
4452 if (is_anonymous) {
4453 return struct_node;
4454 } else {
4455 add_global_weak_alias(c, bare_name, full_type_name);
4456 add_global_var(c, full_type_name, struct_node);
4457 return trans_create_node_symbol(c, full_type_name);
4458 }
4459}
4460
4461static AstNode *trans_ap_value(Context *c, const ZigClangAPValue *ap_value, ZigClangQualType qt,
4462 ZigClangSourceLocation source_loc)
4463{
4464 switch (ZigClangAPValue_getKind(ap_value)) {
4465 case ZigClangAPValueInt:
4466 return trans_create_node_apint(c, ZigClangAPValue_getInt(ap_value));
4467 case ZigClangAPValueNone:
4468 return trans_create_node(c, NodeTypeUndefinedLiteral);
4469 case ZigClangAPValueArray: {
4470 emit_warning(c, source_loc, "TODO add a test case for this code");
4471
4472 unsigned init_count = ZigClangAPValue_getArrayInitializedElts(ap_value);
4473 unsigned all_count = ZigClangAPValue_getArraySize(ap_value);
4474 unsigned leftover_count = all_count - init_count;
4475 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
4476 AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);
4477 if (leftover_count != 0) { // We can't use the size of the final array for a partial initializer.
4478 bigint_init_unsigned(arr_type_node->data.array_type.size->data.int_literal.bigint, init_count);
4479 }
4480 init_node->data.container_init_expr.type = arr_type_node;
4481 init_node->data.container_init_expr.kind = ContainerInitKindArray;
4482
4483 const ZigClangType *qt_type = ZigClangQualType_getTypePtr(qt);
4484 ZigClangQualType child_qt = ZigClangArrayType_getElementType(ZigClangType_getAsArrayTypeUnsafe(qt_type));
4485
4486 for (size_t i = 0; i < init_count; i += 1) {
4487 const ZigClangAPValue *elem_ap_val = ZigClangAPValue_getArrayInitializedElt(ap_value, i);
4488 AstNode *elem_node = trans_ap_value(c, elem_ap_val, child_qt, source_loc);
4489 if (elem_node == nullptr)
4490 return nullptr;
4491 init_node->data.container_init_expr.entries.append(elem_node);
4492 }
4493 if (leftover_count == 0) {
4494 return init_node;
4495 }
4496
4497 const ZigClangAPValue *filler_ap_val = ZigClangAPValue_getArrayFiller(ap_value);
4498 AstNode *filler_node = trans_ap_value(c, filler_ap_val, child_qt, source_loc);
4499 if (filler_node == nullptr)
4500 return nullptr;
4501
4502 AstNode* filler_arr_type = trans_create_node(c, NodeTypeArrayType);
4503 *filler_arr_type = *arr_type_node;
4504 filler_arr_type->data.array_type.size = trans_create_node_unsigned(c, 1);
4505
4506 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
4507 filler_arr_1->data.container_init_expr.type = filler_arr_type;
4508 filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
4509 filler_arr_1->data.container_init_expr.entries.append(filler_node);
4510
4511 AstNode *rhs_node;
4512 if (leftover_count == 1) {
4513 rhs_node = filler_arr_1;
4514 } else {
4515 AstNode *amt_node = trans_create_node_unsigned(c, leftover_count);
4516 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
4517 }
4518
4519 if (init_count == 0) {
4520 return rhs_node;
4521 }
4522
4523 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
4524 }
4525 case ZigClangAPValueLValue: {
4526 const ZigClangAPValueLValueBase lval_base = ZigClangAPValue_getLValueBase(ap_value);
4527 if (const ZigClangExpr *expr = ZigClangAPValueLValueBase_dyn_cast_Expr(lval_base)) {
4528 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
4529 }
4530 emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");
4531 return nullptr;
4532 }
4533 case ZigClangAPValueFloat:
4534 emit_warning(c, source_loc, "unsupported initializer value kind: Float");
4535 return nullptr;
4536 case ZigClangAPValueComplexInt:
4537 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
4538 return nullptr;
4539 case ZigClangAPValueComplexFloat:
4540 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
4541 return nullptr;
4542 case ZigClangAPValueVector:
4543 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
4544 return nullptr;
4545 case ZigClangAPValueStruct:
4546 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
4547 return nullptr;
4548 case ZigClangAPValueUnion:
4549 emit_warning(c, source_loc, "unsupported initializer value kind: Union");
4550 return nullptr;
4551 case ZigClangAPValueMemberPointer:
4552 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
4553 return nullptr;
4554 case ZigClangAPValueAddrLabelDiff:
4555 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
4556 return nullptr;
4557 case ZigClangAPValueIndeterminate:
4558 emit_warning(c, source_loc, "unsupported initializer value kind: Indeterminate");
4559 return nullptr;
4560 case ZigClangAPValueFixedPoint:
4561 emit_warning(c, source_loc, "unsupported initializer value kind: FixedPoint");
4562 return nullptr;
4563 }
4564 zig_unreachable();
4565}
4566
4567static void visit_var_decl(Context *c, const ZigClangVarDecl *var_decl) {
4568 Buf *name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)var_decl));
4569
4570 switch (ZigClangVarDecl_getTLSKind(var_decl)) {
4571 case ZigClangVarDecl_TLSKind_None:
4572 break;
4573 case ZigClangVarDecl_TLSKind_Static:
4574 emit_warning(c, ZigClangVarDecl_getLocation(var_decl),
4575 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
4576 return;
4577 case ZigClangVarDecl_TLSKind_Dynamic:
4578 emit_warning(c, ZigClangVarDecl_getLocation(var_decl),
4579 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
4580 return;
4581 }
4582
4583 ZigClangQualType qt = ZigClangVarDecl_getType(var_decl);
4584 AstNode *var_type = trans_qual_type(c, qt, ZigClangVarDecl_getLocation(var_decl));
4585 if (var_type == nullptr) {
4586 emit_warning(c, ZigClangVarDecl_getLocation(var_decl), "ignoring variable '%s' - unresolved type", buf_ptr(name));
4587 return;
4588 }
4589
4590 bool is_extern = ZigClangVarDecl_hasExternalStorage(var_decl);
4591 bool is_static = ZigClangVarDecl_isFileVarDecl(var_decl);
4592 bool is_const = ZigClangQualType_isConstQualified(qt);
4593
4594 if (is_static && !is_extern) {
4595 AstNode *init_node;
4596 if (ZigClangVarDecl_hasInit(var_decl)) {
4597 const ZigClangAPValue *ap_value = ZigClangVarDecl_evaluateValue(var_decl);
4598 if (ap_value == nullptr) {
4599 emit_warning(c, ZigClangVarDecl_getLocation(var_decl),
4600 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
4601 return;
4602 }
4603 init_node = trans_ap_value(c, ap_value, qt, ZigClangVarDecl_getLocation(var_decl));
4604 if (init_node == nullptr)
4605 return;
4606 } else {
4607 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
4608 }
4609
4610 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, init_node);
4611 add_top_level_decl(c, name, var_node);
4612 return;
4613 }
4614
4615 if (is_extern) {
4616 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, nullptr);
4617 var_node->data.variable_declaration.is_extern = true;
4618 add_top_level_decl(c, name, var_node);
4619 return;
4620 }
4621
4622 emit_warning(c, ZigClangVarDecl_getLocation(var_decl),
4623 "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));
4624 return;
4625}
4626
4627static bool decl_visitor(void *context, const ZigClangDecl *decl) {
4628 Context *c = (Context*)context;
4629
4630 switch (ZigClangDecl_getKind(decl)) {
4631 case ZigClangDeclFunction:
4632 visit_fn_decl(c, reinterpret_cast<const ZigClangFunctionDecl*>(decl));
4633 break;
4634 case ZigClangDeclTypedef:
4635 resolve_typedef_decl(c, reinterpret_cast<const ZigClangTypedefNameDecl *>(decl));
4636 break;
4637 case ZigClangDeclEnum:
4638 resolve_enum_decl(c, reinterpret_cast<const ZigClangEnumDecl *>(decl));
4639 break;
4640 case ZigClangDeclRecord:
4641 resolve_record_decl(c, reinterpret_cast<const ZigClangRecordDecl *>(decl));
4642 break;
4643 case ZigClangDeclVar:
4644 visit_var_decl(c, reinterpret_cast<const ZigClangVarDecl *>(decl));
4645 break;
4646 default:
4647 emit_warning(c, ZigClangDecl_getLocation(decl), "ignoring %s decl", ZigClangDecl_getDeclKindName(decl));
4648 }
4649
4650 return true;
4651}
4652
4653static bool name_exists_global(Context *c, Buf *name) {
4654 return get_global(c, name) != nullptr;
4655}
4656
4657static bool name_exists_scope(Context *c, Buf *name, TransScope *scope) {
4658 while (scope != nullptr) {
4659 if (scope->id == TransScopeIdVar) {
4660 TransScopeVar *var_scope = (TransScopeVar *)scope;
4661 if (buf_eql_buf(name, var_scope->zig_name)) {
4662 return true;
4663 }
4664 }
4665 scope = scope->parent;
4666 }
4667 return name_exists_global(c, name);
4668}
4669
4670static Buf *get_unique_name(Context *c, Buf *name, TransScope *scope) {
4671 Buf *proposed_name = name;
4672 int count = 0;
4673 while (name_exists_scope(c, proposed_name, scope)) {
4674 if (proposed_name == name) {
4675 proposed_name = buf_alloc();
4676 }
4677 buf_resize(proposed_name, 0);
4678 buf_appendf(proposed_name, "%s_%d", buf_ptr(name), count);
4679 count += 1;
4680 }
4681 return proposed_name;
4682}
4683
4684static TransScopeRoot *trans_scope_root_create(Context *c) {
4685 TransScopeRoot *result = allocate<TransScopeRoot>(1);
4686 result->base.id = TransScopeIdRoot;
4687 return result;
4688}
4689
4690static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope) {
4691 TransScopeWhile *result = allocate<TransScopeWhile>(1);
4692 result->base.id = TransScopeIdWhile;
4693 result->base.parent = parent_scope;
4694 result->node = trans_create_node(c, NodeTypeWhileExpr);
4695 return result;
4696}
4697
4698static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope) {
4699 TransScopeBlock *result = allocate<TransScopeBlock>(1);
4700 result->base.id = TransScopeIdBlock;
4701 result->base.parent = parent_scope;
4702 result->node = trans_create_node(c, NodeTypeBlock);
4703 return result;
4704}
4705
4706static TransScopeVar *trans_scope_var_create(Context *c, TransScope *parent_scope, Buf *wanted_name) {
4707 TransScopeVar *result = allocate<TransScopeVar>(1);
4708 result->base.id = TransScopeIdVar;
4709 result->base.parent = parent_scope;
4710 result->c_name = wanted_name;
4711 result->zig_name = get_unique_name(c, wanted_name, parent_scope);
4712 return result;
4713}
4714
4715static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *parent_scope) {
4716 TransScopeSwitch *result = allocate<TransScopeSwitch>(1);
4717 result->base.id = TransScopeIdSwitch;
4718 result->base.parent = parent_scope;
4719 result->switch_node = trans_create_node(c, NodeTypeSwitchExpr);
4720 return result;
4721}
4722
4723static TransScopeBlock *trans_scope_block_find(TransScope *scope) {
4724 while (scope != nullptr) {
4725 if (scope->id == TransScopeIdBlock) {
4726 return (TransScopeBlock *)scope;
4727 }
4728 scope = scope->parent;
4729 }
4730 return nullptr;
4731}
4732
4733static void render_aliases(Context *c) {
4734 for (size_t i = 0; i < c->aliases.length; i += 1) {
4735 Alias *alias = &c->aliases.at(i);
4736 if (name_exists_global(c, alias->new_name))
4737 continue;
4738
4739 add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name));
4740 }
4741}
4742
4743static AstNode *trans_lookup_ast_container_typeof(Context *c, AstNode *ref_node);
4744
4745static AstNode *trans_lookup_ast_container(Context *c, AstNode *type_node) {
4746 if (type_node == nullptr) {
4747 return nullptr;
4748 } else if (type_node->type == NodeTypeContainerDecl) {
4749 return type_node;
4750 } else if (type_node->type == NodeTypePrefixOpExpr) {
4751 return type_node;
4752 } else if (type_node->type == NodeTypeSymbol) {
4753 AstNode *existing_node = get_global(c, type_node->data.symbol_expr.symbol);
4754 if (existing_node == nullptr)
4755 return nullptr;
4756 if (existing_node->type != NodeTypeVariableDeclaration)
4757 return nullptr;
4758 return trans_lookup_ast_container(c, existing_node->data.variable_declaration.expr);
4759 } else if (type_node->type == NodeTypeFieldAccessExpr) {
4760 AstNode *container_node = trans_lookup_ast_container_typeof(c, type_node->data.field_access_expr.struct_expr);
4761 if (container_node == nullptr)
4762 return nullptr;
4763 if (container_node->type != NodeTypeContainerDecl)
4764 return container_node;
4765
4766 for (size_t i = 0; i < container_node->data.container_decl.fields.length; i += 1) {
4767 AstNode *field_node = container_node->data.container_decl.fields.items[i];
4768 if (buf_eql_buf(field_node->data.struct_field.name, type_node->data.field_access_expr.field_name)) {
4769 return trans_lookup_ast_container(c, field_node->data.struct_field.type);
4770 }
4771 }
4772 return nullptr;
4773 } else {
4774 return nullptr;
4775 }
4776}
4777
4778static AstNode *trans_lookup_ast_container_typeof(Context *c, AstNode *ref_node) {
4779 if (ref_node->type == NodeTypeSymbol) {
4780 AstNode *existing_node = get_global(c, ref_node->data.symbol_expr.symbol);
4781 if (existing_node == nullptr)
4782 return nullptr;
4783 if (existing_node->type != NodeTypeVariableDeclaration)
4784 return nullptr;
4785 return trans_lookup_ast_container(c, existing_node->data.variable_declaration.type);
4786 } else if (ref_node->type == NodeTypeFieldAccessExpr) {
4787 AstNode *container_node = trans_lookup_ast_container_typeof(c, ref_node->data.field_access_expr.struct_expr);
4788 if (container_node == nullptr)
4789 return nullptr;
4790 if (container_node->type != NodeTypeContainerDecl)
4791 return container_node;
4792 for (size_t i = 0; i < container_node->data.container_decl.fields.length; i += 1) {
4793 AstNode *field_node = container_node->data.container_decl.fields.items[i];
4794 if (buf_eql_buf(field_node->data.struct_field.name, ref_node->data.field_access_expr.field_name)) {
4795 return trans_lookup_ast_container(c, field_node->data.struct_field.type);
4796 }
4797 }
4798 return nullptr;
4799 } else {
4800 return nullptr;
4801 }
4802}
4803
4804static AstNode *trans_lookup_ast_maybe_fn(Context *c, AstNode *ref_node) {
4805 AstNode *prefix_node = trans_lookup_ast_container_typeof(c, ref_node);
4806 if (prefix_node == nullptr)
4807 return nullptr;
4808 if (prefix_node->type != NodeTypePrefixOpExpr)
4809 return nullptr;
4810 if (prefix_node->data.prefix_op_expr.prefix_op != PrefixOpOptional)
4811 return nullptr;
4812
4813 AstNode *fn_proto_node = prefix_node->data.prefix_op_expr.primary_expr;
4814 if (fn_proto_node->type != NodeTypeFnProto)
4815 return nullptr;
4816
4817 return fn_proto_node;
4818}
4819
4820static void render_macros(Context *c) {
4821 auto it = c->macro_table.entry_iterator();
4822 for (;;) {
4823 auto *entry = it.next();
4824 if (!entry)
4825 break;
4826
4827 AstNode *proto_node;
4828 AstNode *value_node = entry->value;
4829 if (value_node->type == NodeTypeFnDef) {
4830 add_top_level_decl(c, value_node->data.fn_def.fn_proto->data.fn_proto.name, value_node);
4831 } else if ((proto_node = trans_lookup_ast_maybe_fn(c, value_node))) {
4832 // If a macro aliases a global variable which is a function pointer, we conclude that
4833 // the macro is intended to represent a function that assumes the function pointer
4834 // variable is non-null and calls it.
4835 AstNode *inline_fn_node = trans_create_node_inline_fn(c, entry->key, value_node, proto_node);
4836 add_top_level_decl(c, entry->key, inline_fn_node);
4837 } else {
4838 add_global_var(c, entry->key, value_node);
4839 }
4840 }
4841}
4842
4843static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok_i);
4844static AstNode *parse_ctok_expr(Context *c, CTokenize *ctok, size_t *tok_i);
4845static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i);
4846
4847static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, bool negate) {
4848 CTok *tok = &ctok->tokens.at(*tok_i);
4849 if (tok->id == CTokIdNumLitInt) {
4850 *tok_i += 1;
4851 switch (tok->data.num_lit_int.suffix) {
4852 case CNumLitSuffixNone:
4853 return trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate);
4854 case CNumLitSuffixL:
4855 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_long");
4856 case CNumLitSuffixU:
4857 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_uint");
4858 case CNumLitSuffixLU:
4859 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulong");
4860 case CNumLitSuffixLL:
4861 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_longlong");
4862 case CNumLitSuffixLLU:
4863 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulonglong");
4864 }
4865 zig_unreachable();
4866 } else if (tok->id == CTokIdNumLitFloat) {
4867 *tok_i += 1;
4868 double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float;
4869 return trans_create_node_float_lit(c, value);
4870 }
4871 return nullptr;
4872}
4873
4874static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
4875 CTok *tok = &ctok->tokens.at(*tok_i);
4876 switch (tok->id) {
4877 case CTokIdCharLit:
4878 *tok_i += 1;
4879 return trans_create_node_unsigned(c, tok->data.char_lit);
4880 case CTokIdStrLit:
4881 *tok_i += 1;
4882 return trans_create_node_str_lit(c, buf_create_from_buf(&tok->data.str_lit));
4883 case CTokIdMinus:
4884 *tok_i += 1;
4885 return parse_ctok_num_lit(c, ctok, tok_i, true);
4886 case CTokIdNumLitInt:
4887 case CTokIdNumLitFloat:
4888 return parse_ctok_num_lit(c, ctok, tok_i, false);
4889 case CTokIdSymbol:
4890 {
4891 *tok_i += 1;
4892 Buf *symbol_name = buf_create_from_buf(&tok->data.symbol);
4893 return trans_create_node_symbol(c, symbol_name);
4894 }
4895 case CTokIdLParen:
4896 {
4897 *tok_i += 1;
4898 AstNode *inner_node = parse_ctok_expr(c, ctok, tok_i);
4899 if (inner_node == nullptr) {
4900 return nullptr;
4901 }
4902
4903 CTok *next_tok = &ctok->tokens.at(*tok_i);
4904 if (next_tok->id == CTokIdRParen) {
4905 *tok_i += 1;
4906 return inner_node;
4907 }
4908
4909 AstNode *node_to_cast = parse_ctok_expr(c, ctok, tok_i);
4910 if (node_to_cast == nullptr) {
4911 return nullptr;
4912 }
4913
4914 CTok *next_tok2 = &ctok->tokens.at(*tok_i);
4915 if (next_tok2->id != CTokIdRParen) {
4916 return nullptr;
4917 }
4918 *tok_i += 1;
4919
4920
4921 //if (@typeId(@TypeOf(x)) == @import("builtin").TypeId.Pointer)
4922 // @ptrCast(dest, x)
4923 //else if (@typeId(@TypeOf(x)) == @import("builtin").TypeId.Integer)
4924 // @intToPtr(dest, x)
4925 //else
4926 // (dest)(x)
4927
4928 AstNode *import_builtin = trans_create_node_builtin_fn_call_str(c, "import");
4929 import_builtin->data.fn_call_expr.params.append(trans_create_node_str_lit(c, buf_create_from_str("builtin")));
4930 AstNode *typeid_type = trans_create_node_field_access_str(c, import_builtin, "TypeId");
4931 AstNode *typeid_pointer = trans_create_node_field_access_str(c, typeid_type, "Pointer");
4932 AstNode *typeid_integer = trans_create_node_field_access_str(c, typeid_type, "Int");
4933 AstNode *typeof_x = trans_create_node_builtin_fn_call_str(c, "TypeOf");
4934 typeof_x->data.fn_call_expr.params.append(node_to_cast);
4935 AstNode *typeid_value = trans_create_node_builtin_fn_call_str(c, "typeId");
4936 typeid_value->data.fn_call_expr.params.append(typeof_x);
4937
4938 AstNode *outer_if_cond = trans_create_node_bin_op(c, typeid_value, BinOpTypeCmpEq, typeid_pointer);
4939 AstNode *inner_if_cond = trans_create_node_bin_op(c, typeid_value, BinOpTypeCmpEq, typeid_integer);
4940 AstNode *inner_if_then = trans_create_node_builtin_fn_call_str(c, "intToPtr");
4941 inner_if_then->data.fn_call_expr.params.append(inner_node);
4942 inner_if_then->data.fn_call_expr.params.append(node_to_cast);
4943 AstNode *inner_if_else = trans_create_node_cast(c, inner_node, node_to_cast);
4944 AstNode *inner_if = trans_create_node_if(c, inner_if_cond, inner_if_then, inner_if_else);
4945 AstNode *outer_if_then = trans_create_node_builtin_fn_call_str(c, "ptrCast");
4946 outer_if_then->data.fn_call_expr.params.append(inner_node);
4947 outer_if_then->data.fn_call_expr.params.append(node_to_cast);
4948 return trans_create_node_if(c, outer_if_cond, outer_if_then, inner_if);
4949 }
4950 case CTokIdDot:
4951 case CTokIdEOF:
4952 case CTokIdRParen:
4953 case CTokIdAsterisk:
4954 case CTokIdBang:
4955 case CTokIdTilde:
4956 case CTokIdShl:
4957 case CTokIdLt:
4958 // not able to make sense of this
4959 return nullptr;
4960 }
4961 zig_unreachable();
4962}
4963
4964static AstNode *parse_ctok_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
4965 return parse_ctok_prefix_op_expr(c, ctok, tok_i);
4966}
4967
4968static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
4969 AstNode *node = parse_ctok_primary_expr(c, ctok, tok_i);
4970 if (node == nullptr)
4971 return nullptr;
4972
4973 while (true) {
4974 CTok *first_tok = &ctok->tokens.at(*tok_i);
4975 if (first_tok->id == CTokIdDot) {
4976 *tok_i += 1;
4977
4978 CTok *name_tok = &ctok->tokens.at(*tok_i);
4979 if (name_tok->id != CTokIdSymbol) {
4980 return nullptr;
4981 }
4982 *tok_i += 1;
4983
4984 node = trans_create_node_field_access(c, node, buf_create_from_buf(&name_tok->data.symbol));
4985 } else if (first_tok->id == CTokIdAsterisk) {
4986 *tok_i += 1;
4987
4988 node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
4989 } else if (first_tok->id == CTokIdShl) {
4990 *tok_i += 1;
4991
4992 AstNode *rhs_node = parse_ctok_expr(c, ctok, tok_i);
4993 if (rhs_node == nullptr)
4994 return nullptr;
4995 node = trans_create_node_bin_op(c, node, BinOpTypeBitShiftLeft, rhs_node);
4996 } else {
4997 return node;
4998 }
4999 }
5000}
5001
5002static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
5003 CTok *op_tok = &ctok->tokens.at(*tok_i);
5004
5005 switch (op_tok->id) {
5006 case CTokIdBang:
5007 {
5008 *tok_i += 1;
5009 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
5010 if (prefix_op_expr == nullptr)
5011 return nullptr;
5012 return trans_create_node_prefix_op(c, PrefixOpBoolNot, prefix_op_expr);
5013 }
5014 case CTokIdMinus:
5015 {
5016 *tok_i += 1;
5017 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
5018 if (prefix_op_expr == nullptr)
5019 return nullptr;
5020 return trans_create_node_prefix_op(c, PrefixOpNegation, prefix_op_expr);
5021 }
5022 case CTokIdTilde:
5023 {
5024 *tok_i += 1;
5025 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
5026 if (prefix_op_expr == nullptr)
5027 return nullptr;
5028 return trans_create_node_prefix_op(c, PrefixOpBinNot, prefix_op_expr);
5029 }
5030 case CTokIdAsterisk:
5031 {
5032 *tok_i += 1;
5033 AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
5034 if (prefix_op_expr == nullptr)
5035 return nullptr;
5036 return trans_create_node_ptr_deref(c, prefix_op_expr);
5037 }
5038 default:
5039 return parse_ctok_suffix_op_expr(c, ctok, tok_i);
5040 }
5041}
5042
5043static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
5044 tokenize_c_macro(ctok, (const uint8_t *)char_ptr);
5045
5046 if (ctok->error) {
5047 return;
5048 }
5049
5050 size_t tok_i = 0;
5051 CTok *name_tok = &ctok->tokens.at(tok_i);
5052 assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name));
5053 tok_i += 1;
5054
5055 AstNode *result_node = parse_ctok_suffix_op_expr(c, ctok, &tok_i);
5056 if (result_node == nullptr) {
5057 return;
5058 }
5059 CTok *eof_tok = &ctok->tokens.at(tok_i);
5060 if (eof_tok->id != CTokIdEOF) {
5061 return;
5062 }
5063 if (result_node->type == NodeTypeSymbol) {
5064 // if it equals itself, ignore. for example, from stdio.h:
5065 // #define stdin stdin
5066 Buf *symbol_name = result_node->data.symbol_expr.symbol;
5067 if (buf_eql_buf(name, symbol_name)) {
5068 return;
5069 }
5070 }
5071 c->macro_table.put(name, result_node);
5072}
5073
5074static void process_preprocessor_entities(Context *c, ZigClangASTUnit *unit) {
5075 CTokenize ctok = {{0}};
5076
5077 // TODO if we see #undef, delete it from the table
5078 for (ZigClangPreprocessingRecord_iterator it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(unit),
5079 it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(unit); it.I != it_end.I; it.I += 1)
5080 {
5081 ZigClangPreprocessedEntity *entity = ZigClangPreprocessingRecord_iterator_deref(it);
5082
5083 switch (ZigClangPreprocessedEntity_getKind(entity)) {
5084 case ZigClangPreprocessedEntity_InvalidKind:
5085 case ZigClangPreprocessedEntity_InclusionDirectiveKind:
5086 case ZigClangPreprocessedEntity_MacroExpansionKind:
5087 continue;
5088 case ZigClangPreprocessedEntity_MacroDefinitionKind:
5089 {
5090 ZigClangMacroDefinitionRecord *macro = reinterpret_cast<ZigClangMacroDefinitionRecord *>(entity);
5091 const char *raw_name = ZigClangMacroDefinitionRecord_getName_getNameStart(macro);
5092 ZigClangSourceLocation begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro);
5093 ZigClangSourceLocation end_loc = ZigClangMacroDefinitionRecord_getSourceRange_getEnd(macro);
5094
5095 if (ZigClangSourceLocation_eq(begin_loc, end_loc)) {
5096 // this means it is a macro without a value
5097 // we don't care about such things
5098 continue;
5099 }
5100 Buf *name = buf_create_from_str(raw_name);
5101 if (name_exists_global(c, name)) {
5102 continue;
5103 }
5104
5105 const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, begin_loc);
5106 process_macro(c, &ctok, name, begin_c);
5107 }
5108 }
5109 }
5110}
5111
5112Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
5113 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
5114 const char **args_begin, const char **args_end,
5115 TranslateMode mode, const char *resources_path)
5116{
5117 Context context = {0};
5118 Context *c = &context;
5119 c->warnings_on = codegen->verbose_cimport;
5120 if (mode == TranslateModeImport) {
5121 c->want_export = false;
5122 } else {
5123 c->want_export = true;
5124 }
5125 c->decl_table.init(8);
5126 c->macro_table.init(8);
5127 c->global_table.init(8);
5128 c->ptr_params.init(8);
5129 c->codegen = codegen;
5130 c->global_scope = trans_scope_root_create(c);
5131
5132 ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len,
5133 resources_path);
5134 if (ast_unit == nullptr) {
5135 if (*errors_len == 0) return ErrorNoMem;
5136 return ErrorCCompileErrors;
5137 }
5138
5139 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
5140 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
5141 c->root = trans_create_node(c, NodeTypeContainerDecl);
5142 c->root->data.container_decl.is_root = true;
5143
5144 ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor);
5145
5146 process_preprocessor_entities(c, ast_unit);
5147
5148 render_macros(c);
5149 render_aliases(c);
5150
5151 *out_root_node = c->root;
5152
5153 ZigClangASTUnit_delete(ast_unit);
5154
5155 return ErrorNone;
5156}
src/translate_c.hpp deleted-24
......@@ -1,24 +0,0 @@
1/*
2 * Copyright (c) 2015 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8
9#ifndef ZIG_PARSEC_HPP
10#define ZIG_PARSEC_HPP
11
12#include "all_types.hpp"
13
14enum TranslateMode {
15 TranslateModeImport,
16 TranslateModeTranslate,
17};
18
19Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
20 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
21 const char **args_begin, const char **args_end,
22 TranslateMode mode, const char *resources_path);
23
24#endif
test/tests.zig+2-51
......@@ -1422,7 +1422,6 @@ pub const TranslateCContext = struct {
14221422 sources: ArrayList(SourceFile),
14231423 expected_lines: ArrayList([]const u8),
14241424 allow_warnings: bool,
1425 stage2: bool,
14261425
14271426 const SourceFile = struct {
14281427 filename: []const u8,
......@@ -1475,7 +1474,7 @@ pub const TranslateCContext = struct {
14751474 var zig_args = ArrayList([]const u8).init(b.allocator);
14761475 zig_args.append(b.zig_exe) catch unreachable;
14771476
1478 const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
1477 const translate_c_cmd = "translate-c";
14791478 zig_args.append(translate_c_cmd) catch unreachable;
14801479 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
14811480
......@@ -1583,7 +1582,6 @@ pub const TranslateCContext = struct {
15831582 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
15841583 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
15851584 .allow_warnings = allow_warnings,
1586 .stage2 = false,
15871585 };
15881586
15891587 tc.addSourceFile(filename, source);
......@@ -1604,53 +1602,6 @@ pub const TranslateCContext = struct {
16041602 self.addCase(tc);
16051603 }
16061604
1607 pub fn addC(
1608 self: *TranslateCContext,
1609 name: []const u8,
1610 source: []const u8,
1611 expected_lines: []const []const u8,
1612 ) void {
1613 const tc = self.create(false, "source.c", name, source, expected_lines);
1614 self.addCase(tc);
1615 }
1616
1617 pub fn add_both(
1618 self: *TranslateCContext,
1619 name: []const u8,
1620 source: []const u8,
1621 expected_lines: []const []const u8,
1622 ) void {
1623 for ([_]bool{ false, true }) |stage2| {
1624 const tc = self.create(false, "source.h", name, source, expected_lines);
1625 tc.stage2 = stage2;
1626 self.addCase(tc);
1627 }
1628 }
1629
1630 pub fn addC_both(
1631 self: *TranslateCContext,
1632 name: []const u8,
1633 source: []const u8,
1634 expected_lines: []const []const u8,
1635 ) void {
1636 for ([_]bool{ false, true }) |stage2| {
1637 const tc = self.create(false, "source.c", name, source, expected_lines);
1638 tc.stage2 = stage2;
1639 self.addCase(tc);
1640 }
1641 }
1642
1643 pub fn add_2(
1644 self: *TranslateCContext,
1645 name: []const u8,
1646 source: []const u8,
1647 expected_lines: []const []const u8,
1648 ) void {
1649 const tc = self.create(false, "source.h", name, source, expected_lines);
1650 tc.stage2 = true;
1651 self.addCase(tc);
1652 }
1653
16541605 pub fn addAllowWarnings(
16551606 self: *TranslateCContext,
16561607 name: []const u8,
......@@ -1664,7 +1615,7 @@ pub const TranslateCContext = struct {
16641615 pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
16651616 const b = self.b;
16661617
1667 const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
1618 const translate_c_cmd = "translate-c";
16681619 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", .{ translate_c_cmd, case.name }) catch unreachable;
16691620 if (self.test_filter) |filter| {
16701621 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
test/translate_c.zig+130-1135
......@@ -1,15 +1,9 @@
11const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
4// add_both - test for stage1 and stage2, in #include mode
5// add - test stage1 only, in #include mode
6// add_2 - test stage2 only
7// addC_both - test for stage1 and stage2, in -c mode
8// addC - test stage1 only, in -c mode
9
104pub fn addCases(cases: *tests.TranslateCContext) void {
115 /////////////// Cases that pass for both stage1/stage2 ////////////////
12 cases.add_both("simple function prototypes",
6 cases.add("simple function prototypes",
137 \\void __attribute__((noreturn)) foo(void);
148 \\int bar(void);
159 , &[_][]const u8{
......@@ -17,7 +11,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1711 \\pub extern fn bar() c_int;
1812 });
1913
20 cases.addC_both("simple var decls",
14 cases.add("simple var decls",
2115 \\void foo(void) {
2216 \\ int a;
2317 \\ char b = 123;
......@@ -33,7 +27,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3327 \\}
3428 });
3529
36 cases.addC_both("ignore result, explicit function arguments",
30 cases.add("ignore result, explicit function arguments",
3731 \\void foo(void) {
3832 \\ int a;
3933 \\ 1;
......@@ -53,7 +47,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
5347 \\}
5448 });
5549
56 cases.addC_both("variables",
50 cases.add("variables",
5751 \\extern int extern_var;
5852 \\static const int int_var = 13;
5953 , &[_][]const u8{
......@@ -62,13 +56,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
6256 \\pub const int_var: c_int = 13;
6357 });
6458
65 cases.add_both("const ptr initializer",
59 cases.add("const ptr initializer",
6660 \\static const char *v0 = "0.0.0";
6761 , &[_][]const u8{
6862 \\pub var v0: [*c]const u8 = "0.0.0";
6963 });
7064
71 cases.addC_both("static incomplete array inside function",
65 cases.add("static incomplete array inside function",
7266 \\void foo(void) {
7367 \\ static const char v2[] = "2.2.2";
7468 \\}
......@@ -78,7 +72,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
7872 \\}
7973 });
8074
81 cases.addC_both("simple function definition",
75 cases.add("simple function definition",
8276 \\void foo(void) {}
8377 \\static void bar(void) {}
8478 , &[_][]const u8{
......@@ -86,7 +80,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
8680 \\pub fn bar() void {}
8781 });
8882
89 cases.add_both("typedef void",
83 cases.add("typedef void",
9084 \\typedef void Foo;
9185 \\Foo fun(Foo *a);
9286 , &[_][]const u8{
......@@ -95,7 +89,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
9589 \\pub extern fn fun(a: ?*Foo) Foo;
9690 });
9791
98 cases.add_both("duplicate typedef",
92 cases.add("duplicate typedef",
9993 \\typedef long foo;
10094 \\typedef int bar;
10195 \\typedef long foo;
......@@ -106,7 +100,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
106100 \\pub const baz = c_int;
107101 });
108102
109 cases.addC_both("casting pointers to ints and ints to pointers",
103 cases.add("casting pointers to ints and ints to pointers",
110104 \\void foo(void);
111105 \\void bar(void) {
112106 \\ void *func_ptr = foo;
......@@ -120,13 +114,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
120114 \\}
121115 });
122116
123 cases.add_both("noreturn attribute",
117 cases.add("noreturn attribute",
124118 \\void foo(void) __attribute__((noreturn));
125119 , &[_][]const u8{
126120 \\pub extern fn foo() noreturn;
127121 });
128122
129 cases.addC_both("add, sub, mul, div, rem",
123 cases.add("add, sub, mul, div, rem",
130124 \\int s() {
131125 \\ int a, b, c;
132126 \\ c = a + b;
......@@ -166,7 +160,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
166160 \\}
167161 });
168162
169 cases.add_both("typedef of function in struct field",
163 cases.add("typedef of function in struct field",
170164 \\typedef void lws_callback_function(void);
171165 \\struct Foo {
172166 \\ void (*func)(void);
......@@ -180,7 +174,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
180174 \\};
181175 });
182176
183 cases.add_both("pointer to struct demoted to opaque due to bit fields",
177 cases.add("pointer to struct demoted to opaque due to bit fields",
184178 \\struct Foo {
185179 \\ unsigned int: 1;
186180 \\};
......@@ -195,13 +189,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
195189 \\};
196190 });
197191
198 cases.add_both("macro with left shift",
192 cases.add("macro with left shift",
199193 \\#define REDISMODULE_READ (1<<0)
200194 , &[_][]const u8{
201195 \\pub const REDISMODULE_READ = 1 << 0;
202196 });
203197
204 cases.add_both("double define struct",
198 cases.add("double define struct",
205199 \\typedef struct Bar Bar;
206200 \\typedef struct Foo Foo;
207201 \\
......@@ -226,7 +220,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
226220 \\pub const Bar = struct_Bar;
227221 });
228222
229 cases.add_both("simple struct",
223 cases.add("simple struct",
230224 \\struct Foo {
231225 \\ int x;
232226 \\ char *y;
......@@ -240,7 +234,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
240234 \\pub const Foo = struct_Foo;
241235 });
242236
243 cases.add_both("self referential struct with function pointer",
237 cases.add("self referential struct with function pointer",
244238 \\struct Foo {
245239 \\ void (*derp)(struct Foo *foo);
246240 \\};
......@@ -252,7 +246,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
252246 \\pub const Foo = struct_Foo;
253247 });
254248
255 cases.add_both("struct prototype used in func",
249 cases.add("struct prototype used in func",
256250 \\struct Foo;
257251 \\struct Foo *some_func(struct Foo *foo, int x);
258252 , &[_][]const u8{
......@@ -263,13 +257,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263257 \\pub const Foo = struct_Foo;
264258 });
265259
266 cases.add_both("#define an unsigned integer literal",
260 cases.add("#define an unsigned integer literal",
267261 \\#define CHANNEL_COUNT 24
268262 , &[_][]const u8{
269263 \\pub const CHANNEL_COUNT = 24;
270264 });
271265
272 cases.add_both("#define referencing another #define",
266 cases.add("#define referencing another #define",
273267 \\#define THING2 THING1
274268 \\#define THING1 1234
275269 , &[_][]const u8{
......@@ -278,7 +272,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
278272 \\pub const THING2 = THING1;
279273 });
280274
281 cases.add_both("circular struct definitions",
275 cases.add("circular struct definitions",
282276 \\struct Bar;
283277 \\
284278 \\struct Foo {
......@@ -298,13 +292,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
298292 \\};
299293 });
300294
301 cases.add_both("#define string",
295 cases.add("#define string",
302296 \\#define foo "a string"
303297 , &[_][]const u8{
304298 \\pub const foo = "a string";
305299 });
306300
307 cases.add_both("zig keywords in C code",
301 cases.add("zig keywords in C code",
308302 \\struct comptime {
309303 \\ int defer;
310304 \\};
......@@ -316,13 +310,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
316310 \\pub const @"comptime" = struct_comptime;
317311 });
318312
319 cases.add_both("macro with parens around negative number",
313 cases.add("macro with parens around negative number",
320314 \\#define LUA_GLOBALSINDEX (-10002)
321315 , &[_][]const u8{
322316 \\pub const LUA_GLOBALSINDEX = -10002;
323317 });
324318
325 cases.add_both(
319 cases.add(
326320 "u integer suffix after 0 (zero) in macro definition",
327321 "#define ZERO 0U",
328322 &[_][]const u8{
......@@ -330,7 +324,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
330324 },
331325 );
332326
333 cases.add_both(
327 cases.add(
334328 "l integer suffix after 0 (zero) in macro definition",
335329 "#define ZERO 0L",
336330 &[_][]const u8{
......@@ -338,7 +332,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
338332 },
339333 );
340334
341 cases.add_both(
335 cases.add(
342336 "ul integer suffix after 0 (zero) in macro definition",
343337 "#define ZERO 0UL",
344338 &[_][]const u8{
......@@ -346,7 +340,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
346340 },
347341 );
348342
349 cases.add_both(
343 cases.add(
350344 "lu integer suffix after 0 (zero) in macro definition",
351345 "#define ZERO 0LU",
352346 &[_][]const u8{
......@@ -354,7 +348,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
354348 },
355349 );
356350
357 cases.add_both(
351 cases.add(
358352 "ll integer suffix after 0 (zero) in macro definition",
359353 "#define ZERO 0LL",
360354 &[_][]const u8{
......@@ -362,7 +356,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
362356 },
363357 );
364358
365 cases.add_both(
359 cases.add(
366360 "ull integer suffix after 0 (zero) in macro definition",
367361 "#define ZERO 0ULL",
368362 &[_][]const u8{
......@@ -370,7 +364,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
370364 },
371365 );
372366
373 cases.add_both(
367 cases.add(
374368 "llu integer suffix after 0 (zero) in macro definition",
375369 "#define ZERO 0LLU",
376370 &[_][]const u8{
......@@ -378,7 +372,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
378372 },
379373 );
380374
381 cases.add_both(
375 cases.add(
382376 "bitwise not on u-suffixed 0 (zero) in macro definition",
383377 "#define NOT_ZERO (~0U)",
384378 &[_][]const u8{
......@@ -386,7 +380,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
386380 },
387381 );
388382
389 cases.addC_both("null statements",
383 cases.add("null statements",
390384 \\void foo(void) {
391385 \\ ;;;;;
392386 \\}
......@@ -402,7 +396,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
402396
403397 if (builtin.os != builtin.Os.windows) {
404398 // Windows treats this as an enum with type c_int
405 cases.add_both("big negative enum init values when C ABI supports long long enums",
399 cases.add("big negative enum init values when C ABI supports long long enums",
406400 \\enum EnumWithInits {
407401 \\ VAL01 = 0,
408402 \\ VAL02 = 1,
......@@ -457,7 +451,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
457451 });
458452 }
459453
460 cases.addC_both("predefined expressions",
454 cases.add("predefined expressions",
461455 \\void foo(void) {
462456 \\ __func__;
463457 \\ __FUNCTION__;
......@@ -471,7 +465,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
471465 \\}
472466 });
473467
474 cases.addC_both("ignore result, no function arguments",
468 cases.add("ignore result, no function arguments",
475469 \\void foo() {
476470 \\ int a;
477471 \\ 1;
......@@ -491,19 +485,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
491485 \\}
492486 });
493487
494 cases.add_both("constant size array",
488 cases.add("constant size array",
495489 \\void func(int array[20]);
496490 , &[_][]const u8{
497491 \\pub extern fn func(array: [*c]c_int) void;
498492 });
499493
500 cases.add_both("__cdecl doesn't mess up function pointers",
494 cases.add("__cdecl doesn't mess up function pointers",
501495 \\void foo(void (__cdecl *fn_ptr)(void));
502496 , &[_][]const u8{
503497 \\pub extern fn foo(fn_ptr: ?extern fn () void) void;
504498 });
505499
506 cases.addC_both("void cast",
500 cases.add("void cast",
507501 \\void foo() {
508502 \\ int a;
509503 \\ (void) a;
......@@ -515,7 +509,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
515509 \\}
516510 });
517511
518 cases.addC_both("implicit cast to void *",
512 cases.add("implicit cast to void *",
519513 \\void *foo() {
520514 \\ unsigned short *x;
521515 \\ return x;
......@@ -527,7 +521,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
527521 \\}
528522 });
529523
530 cases.addC_both("null pointer implicit cast",
524 cases.add("null pointer implicit cast",
531525 \\int* foo(void) {
532526 \\ return 0;
533527 \\}
......@@ -537,7 +531,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
537531 \\}
538532 });
539533
540 cases.add_both("simple union",
534 cases.add("simple union",
541535 \\union Foo {
542536 \\ int x;
543537 \\ double y;
......@@ -551,7 +545,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
551545 \\pub const Foo = union_Foo;
552546 });
553547
554 cases.addC_both("string literal",
548 cases.add("string literal",
555549 \\const char *foo(void) {
556550 \\ return "bar";
557551 \\}
......@@ -561,7 +555,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
561555 \\}
562556 });
563557
564 cases.addC_both("return void",
558 cases.add("return void",
565559 \\void foo(void) {
566560 \\ return;
567561 \\}
......@@ -571,7 +565,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
571565 \\}
572566 });
573567
574 cases.addC_both("for loop",
568 cases.add("for loop",
575569 \\void foo(void) {
576570 \\ for (int i = 0; i; i = i + 1) { }
577571 \\}
......@@ -584,7 +578,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
584578 \\}
585579 });
586580
587 cases.addC_both("empty for loop",
581 cases.add("empty for loop",
588582 \\void foo(void) {
589583 \\ for (;;) { }
590584 \\}
......@@ -594,7 +588,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
594588 \\}
595589 });
596590
597 cases.addC_both("break statement",
591 cases.add("break statement",
598592 \\void foo(void) {
599593 \\ for (;;) {
600594 \\ break;
......@@ -608,7 +602,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
608602 \\}
609603 });
610604
611 cases.addC_both("continue statement",
605 cases.add("continue statement",
612606 \\void foo(void) {
613607 \\ for (;;) {
614608 \\ continue;
......@@ -622,7 +616,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
622616 \\}
623617 });
624618
625 cases.addC_both("pointer casting",
619 cases.add("pointer casting",
626620 \\float *ptrcast() {
627621 \\ int *a;
628622 \\ return (float *)a;
......@@ -634,7 +628,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
634628 \\}
635629 });
636630
637 cases.addC_both("pointer conversion with different alignment",
631 cases.add("pointer conversion with different alignment",
638632 \\void test_ptr_cast() {
639633 \\ void *p;
640634 \\ {
......@@ -668,7 +662,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
668662 \\}
669663 });
670664
671 cases.addC_both("while on non-bool",
665 cases.add("while on non-bool",
672666 \\int while_none_bool() {
673667 \\ int a;
674668 \\ float b;
......@@ -690,7 +684,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
690684 \\}
691685 });
692686
693 cases.addC_both("for on non-bool",
687 cases.add("for on non-bool",
694688 \\int for_none_bool() {
695689 \\ int a;
696690 \\ float b;
......@@ -712,7 +706,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
712706 \\}
713707 });
714708
715 cases.addC_both("bitshift",
709 cases.add("bitshift",
716710 \\int foo(void) {
717711 \\ return (1 << 2) >> 1;
718712 \\}
......@@ -722,7 +716,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
722716 \\}
723717 });
724718
725 cases.addC_both("sizeof",
719 cases.add("sizeof",
726720 \\#include <stddef.h>
727721 \\size_t size_of(void) {
728722 \\ return sizeof(int);
......@@ -733,7 +727,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
733727 \\}
734728 });
735729
736 cases.addC_both("normal deref",
730 cases.add("normal deref",
737731 \\void foo() {
738732 \\ int *x;
739733 \\ *x = 1;
......@@ -745,7 +739,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
745739 \\}
746740 });
747741
748 cases.addC_both("address of operator",
742 cases.add("address of operator",
749743 \\int foo(void) {
750744 \\ int x = 1234;
751745 \\ int *ptr = &x;
......@@ -759,7 +753,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
759753 \\}
760754 });
761755
762 cases.addC_both("bin not",
756 cases.add("bin not",
763757 \\int foo() {
764758 \\ int x;
765759 \\ return ~x;
......@@ -771,7 +765,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
771765 \\}
772766 });
773767
774 cases.addC_both("bool not",
768 cases.add("bool not",
775769 \\int foo() {
776770 \\ int a;
777771 \\ float b;
......@@ -793,7 +787,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
793787 \\}
794788 });
795789
796 cases.addC("__extension__ cast",
790 cases.add("__extension__ cast",
797791 \\int foo(void) {
798792 \\ return __extension__ 1;
799793 \\}
......@@ -805,16 +799,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
805799
806800 if (builtin.os != builtin.Os.windows) {
807801 // sysv_abi not currently supported on windows
808 cases.add_both("Macro qualified functions",
802 cases.add("Macro qualified functions",
809803 \\void __attribute__((sysv_abi)) foo(void);
810804 , &[_][]const u8{
811805 \\pub extern fn foo() void;
812806 });
813807 }
814808
815 /////////////// Cases that pass for only stage2 ////////////////
816
817 cases.add_2("Forward-declared enum",
809 cases.add("Forward-declared enum",
818810 \\extern enum enum_ty my_enum;
819811 \\enum enum_ty { FOO };
820812 , &[_][]const u8{
......@@ -825,7 +817,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
825817 \\pub extern var my_enum: enum_enum_ty;
826818 });
827819
828 cases.add_2("Parameterless function pointers",
820 cases.add("Parameterless function pointers",
829821 \\typedef void (*fn0)();
830822 \\typedef void (*fn1)(char);
831823 , &[_][]const u8{
......@@ -833,7 +825,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
833825 \\pub const fn1 = ?extern fn (u8) void;
834826 });
835827
836 cases.add_2("Parameterless function prototypes",
828 cases.add("Parameterless function prototypes",
837829 \\void a() {}
838830 \\void b(void) {}
839831 \\void c();
......@@ -845,7 +837,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
845837 \\pub extern fn d() void;
846838 });
847839
848 cases.add_2("variable declarations",
840 cases.add("variable declarations",
849841 \\extern char arr0[] = "hello";
850842 \\static char arr1[] = "hello";
851843 \\char arr2[] = "hello";
......@@ -855,7 +847,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
855847 \\pub export var arr2: [*c]u8 = "hello";
856848 });
857849
858 cases.add_2("array initializer expr",
850 cases.add("array initializer expr",
859851 \\static void foo(void){
860852 \\ char arr[10] ={1};
861853 \\ char *arr1[10] ={0};
......@@ -871,7 +863,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
871863 \\}
872864 });
873865
874 cases.add_2("enums",
866 cases.add("enums",
875867 \\typedef enum {
876868 \\ a,
877869 \\ b,
......@@ -938,61 +930,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
938930 \\pub const Baz = struct_Baz;
939931 });
940932
941 cases.add_2("#define a char literal",
933 cases.add("#define a char literal",
942934 \\#define A_CHAR 'a'
943935 , &[_][]const u8{
944936 \\pub const A_CHAR = 'a';
945937 });
946938
947 cases.add_2("comment after integer literal",
939 cases.add("comment after integer literal",
948940 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
949941 , &[_][]const u8{
950942 \\pub const SDL_INIT_VIDEO = 0x00000020;
951943 });
952944
953 cases.add_2("u integer suffix after hex literal",
945 cases.add("u integer suffix after hex literal",
954946 \\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
955947 , &[_][]const u8{
956948 \\pub const SDL_INIT_VIDEO = @as(c_uint, 0x00000020);
957949 });
958950
959 cases.add_2("l integer suffix after hex literal",
951 cases.add("l integer suffix after hex literal",
960952 \\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
961953 , &[_][]const u8{
962954 \\pub const SDL_INIT_VIDEO = @as(c_long, 0x00000020);
963955 });
964956
965 cases.add_2("ul integer suffix after hex literal",
957 cases.add("ul integer suffix after hex literal",
966958 \\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
967959 , &[_][]const u8{
968960 \\pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020);
969961 });
970962
971 cases.add_2("lu integer suffix after hex literal",
963 cases.add("lu integer suffix after hex literal",
972964 \\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
973965 , &[_][]const u8{
974966 \\pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020);
975967 });
976968
977 cases.add_2("ll integer suffix after hex literal",
969 cases.add("ll integer suffix after hex literal",
978970 \\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
979971 , &[_][]const u8{
980972 \\pub const SDL_INIT_VIDEO = @as(c_longlong, 0x00000020);
981973 });
982974
983 cases.add_2("ull integer suffix after hex literal",
975 cases.add("ull integer suffix after hex literal",
984976 \\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
985977 , &[_][]const u8{
986978 \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020);
987979 });
988980
989 cases.add_2("llu integer suffix after hex literal",
981 cases.add("llu integer suffix after hex literal",
990982 \\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
991983 , &[_][]const u8{
992984 \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020);
993985 });
994986
995 cases.add_2("generate inline func for #define global extern fn",
987 cases.add("generate inline func for #define global extern fn",
996988 \\extern void (*fn_ptr)(void);
997989 \\#define foo fn_ptr
998990 \\
......@@ -1012,7 +1004,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10121004 \\}
10131005 });
10141006
1015 cases.add_2("macros with field targets",
1007 cases.add("macros with field targets",
10161008 \\typedef unsigned int GLbitfield;
10171009 \\typedef void (*PFNGLCLEARPROC) (GLbitfield mask);
10181010 \\typedef void(*OpenGLProc)(void);
......@@ -1047,13 +1039,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10471039 \\pub const OpenGLProcs = union_OpenGLProcs;
10481040 });
10491041
1050 cases.add_2("macro pointer cast",
1042 cases.add("macro pointer cast",
10511043 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
10521044 , &[_][]const u8{
10531045 \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
10541046 });
10551047
1056 cases.add_2("basic macro function",
1048 cases.add("basic macro function",
10571049 \\extern int c;
10581050 \\#define BASIC(c) (c*2)
10591051 , &[_][]const u8{
......@@ -1064,7 +1056,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10641056 \\}
10651057 });
10661058
1067 cases.add_2("macro defines string literal with hex",
1059 cases.add("macro defines string literal with hex",
10681060 \\#define FOO "aoeu\xab derp"
10691061 \\#define FOO2 "aoeu\x0007a derp"
10701062 \\#define FOO_CHAR '\xfF'
......@@ -1076,7 +1068,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10761068 \\pub const FOO_CHAR = '\xff';
10771069 });
10781070
1079 cases.add_2("variable aliasing",
1071 cases.add("variable aliasing",
10801072 \\static long a = 2;
10811073 \\static long b = 2;
10821074 \\static int c = 4;
......@@ -1105,7 +1097,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11051097 \\}
11061098 });
11071099
1108 cases.add_2("comma operator",
1100 cases.add("comma operator",
11091101 \\int foo(char c) {
11101102 \\ 2, 4;
11111103 \\ return 2, 4, 6;
......@@ -1121,7 +1113,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11211113 \\}
11221114 });
11231115
1124 cases.add_2("wors-case assign",
1116 cases.add("wors-case assign",
11251117 \\int foo(char c) {
11261118 \\ int a;
11271119 \\ int b;
......@@ -1140,7 +1132,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11401132 \\}
11411133 });
11421134
1143 cases.add_2("if statements",
1135 cases.add("if statements",
11441136 \\int foo(char c) {
11451137 \\ if (2) {
11461138 \\ int a = 2;
......@@ -1164,7 +1156,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11641156 \\}
11651157 });
11661158
1167 cases.add_2("while loops",
1159 cases.add("while loops",
11681160 \\int foo() {
11691161 \\ int a = 5;
11701162 \\ while (2)
......@@ -1204,7 +1196,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12041196 \\}
12051197 });
12061198
1207 cases.add_2("for loops",
1199 cases.add("for loops",
12081200 \\int foo() {
12091201 \\ for (int i = 2, b = 4; i + 2; i = 2) {
12101202 \\ int a = 2;
......@@ -1228,13 +1220,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12281220 \\}
12291221 });
12301222
1231 cases.add_2("shadowing primitive types",
1223 cases.add("shadowing primitive types",
12321224 \\unsigned anyerror = 2;
12331225 , &[_][]const u8{
12341226 \\pub export var _anyerror: c_uint = @as(c_uint, 2);
12351227 });
12361228
1237 cases.add_2("floats",
1229 cases.add("floats",
12381230 \\float a = 3.1415;
12391231 \\double b = 3.1415;
12401232 \\int c = 3.1415;
......@@ -1246,7 +1238,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12461238 \\pub export var d: f64 = @intToFloat(f64, 3);
12471239 });
12481240
1249 cases.add_2("conditional operator",
1241 cases.add("conditional operator",
12501242 \\int bar(void) {
12511243 \\ if (2 ? 5 : 5 ? 4 : 6) 2;
12521244 \\ return 2 ? 5 : 5 ? 4 : 6;
......@@ -1258,7 +1250,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12581250 \\}
12591251 });
12601252
1261 cases.add_2("switch on int",
1253 cases.add("switch on int",
12621254 \\int switch_fn(int i) {
12631255 \\ int res = 0;
12641256 \\ switch (i) {
......@@ -1301,7 +1293,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13011293 \\}
13021294 });
13031295
1304 cases.add_2("type referenced struct",
1296 cases.add("type referenced struct",
13051297 \\struct Foo {
13061298 \\ struct Bar{
13071299 \\ int b;
......@@ -1317,19 +1309,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13171309 \\};
13181310 });
13191311
1320 cases.add_2("undefined array global",
1312 cases.add("undefined array global",
13211313 \\int array[100] = {};
13221314 , &[_][]const u8{
13231315 \\pub export var array: [100]c_int = .{0} ** 100;
13241316 });
13251317
1326 cases.add_2("restrict -> noalias",
1318 cases.add("restrict -> noalias",
13271319 \\void foo(void *restrict bar, void *restrict);
13281320 , &[_][]const u8{
13291321 \\pub extern fn foo(noalias bar: ?*c_void, noalias ?*c_void) void;
13301322 });
13311323
1332 cases.add_2("assign",
1324 cases.add("assign",
13331325 \\int max(int a) {
13341326 \\ int tmp;
13351327 \\ tmp = a;
......@@ -1344,7 +1336,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13441336 \\}
13451337 });
13461338
1347 cases.add_2("chaining assign",
1339 cases.add("chaining assign",
13481340 \\void max(int a) {
13491341 \\ int b, c;
13501342 \\ c = b = a;
......@@ -1362,7 +1354,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13621354 \\}
13631355 });
13641356
1365 cases.add_2("anonymous enum",
1357 cases.add("anonymous enum",
13661358 \\enum {
13671359 \\ One,
13681360 \\ Two,
......@@ -1376,7 +1368,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13761368 \\};
13771369 });
13781370
1379 cases.add_2("c style cast",
1371 cases.add("c style cast",
13801372 \\int float_to_int(float a) {
13811373 \\ return (int)a;
13821374 \\}
......@@ -1387,7 +1379,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13871379 \\}
13881380 });
13891381
1390 cases.add_2("escape sequences",
1382 cases.add("escape sequences",
13911383 \\const char *escapes() {
13921384 \\char a = '\'',
13931385 \\ b = '\\',
......@@ -1420,7 +1412,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14201412 \\}
14211413 });
14221414
1423 cases.add_2("do loop",
1415 cases.add("do loop",
14241416 \\void foo(void) {
14251417 \\ int a = 2;
14261418 \\ do {
......@@ -1447,7 +1439,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14471439 \\}
14481440 });
14491441
1450 cases.add_2("logical and, logical or, on non-bool values, extra parens",
1442 cases.add("logical and, logical or, on non-bool values, extra parens",
14511443 \\enum Foo {
14521444 \\ FooA,
14531445 \\ FooB,
......@@ -1500,7 +1492,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15001492 \\pub const Foo = enum_Foo;
15011493 });
15021494
1503 cases.add_2("qualified struct and enum",
1495 cases.add("qualified struct and enum",
15041496 \\struct Foo {
15051497 \\ int x;
15061498 \\ int y;
......@@ -1526,7 +1518,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15261518 \\pub const Bar = enum_Bar;
15271519 });
15281520
1529 cases.add_2("bitwise binary operators, simpler parens",
1521 cases.add("bitwise binary operators, simpler parens",
15301522 \\int max(int a, int b) {
15311523 \\ return (a & b) ^ (a | b);
15321524 \\}
......@@ -1538,7 +1530,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15381530 \\}
15391531 });
15401532
1541 cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
1533 cases.add("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
15421534 \\int test_comparisons(int a, int b) {
15431535 \\ int c = (a < b);
15441536 \\ int d = (a > b);
......@@ -1564,7 +1556,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15641556 \\}
15651557 });
15661558
1567 cases.add_2("==, !=",
1559 cases.add("==, !=",
15681560 \\int max(int a, int b) {
15691561 \\ if (a == b)
15701562 \\ return a;
......@@ -1582,7 +1574,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15821574 \\}
15831575 });
15841576
1585 cases.add_2("typedeffed bool expression",
1577 cases.add("typedeffed bool expression",
15861578 \\typedef char* yes;
15871579 \\void foo(void) {
15881580 \\ yes a;
......@@ -1596,7 +1588,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15961588 \\}
15971589 });
15981590
1599 cases.add_2("statement expression",
1591 cases.add("statement expression",
16001592 \\int foo(void) {
16011593 \\ return ({
16021594 \\ int a = 1;
......@@ -1614,7 +1606,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16141606 \\}
16151607 });
16161608
1617 cases.add_2("field access expression",
1609 cases.add("field access expression",
16181610 \\#define ARROW a->b
16191611 \\#define DOT a.b
16201612 \\extern struct Foo {
......@@ -1643,7 +1635,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16431635 \\pub const ARROW = a.*.b;
16441636 });
16451637
1646 cases.add_2("array access",
1638 cases.add("array access",
16471639 \\#define ACCESS array[2]
16481640 \\int array[100] = {};
16491641 \\int foo(int index) {
......@@ -1659,7 +1651,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16591651 \\pub const ACCESS = array[2];
16601652 });
16611653
1662 cases.add_2("macro call",
1654 cases.add("macro call",
16631655 \\#define CALL(arg) bar(arg)
16641656 , &[_][]const u8{
16651657 \\pub inline fn CALL(arg: var) @TypeOf(bar(arg)) {
......@@ -1667,7 +1659,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16671659 \\}
16681660 });
16691661
1670 cases.add_2("logical and, logical or",
1662 cases.add("logical and, logical or",
16711663 \\int max(int a, int b) {
16721664 \\ if (a < b || a == b)
16731665 \\ return b;
......@@ -1685,7 +1677,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16851677 \\}
16861678 });
16871679
1688 cases.add_2("if statement",
1680 cases.add("if statement",
16891681 \\int max(int a, int b) {
16901682 \\ if (a < b)
16911683 \\ return b;
......@@ -1707,7 +1699,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17071699 \\}
17081700 });
17091701
1710 cases.add_2("if on non-bool",
1702 cases.add("if on non-bool",
17111703 \\enum SomeEnum { A, B, C };
17121704 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
17131705 \\ if (a) return 0;
......@@ -1735,7 +1727,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17351727 \\}
17361728 });
17371729
1738 cases.add_2("simple data types",
1730 cases.add("simple data types",
17391731 \\#include <stdint.h>
17401732 \\int foo(char a, unsigned char b, signed char c);
17411733 \\int foo(char a, unsigned char b, signed char c); // test a duplicate prototype
......@@ -1747,7 +1739,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17471739 \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
17481740 });
17491741
1750 cases.add_2("simple function",
1742 cases.add("simple function",
17511743 \\int abs(int a) {
17521744 \\ return a < 0 ? -a : a;
17531745 \\}
......@@ -1758,7 +1750,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17581750 \\}
17591751 });
17601752
1761 cases.add_2("post increment",
1753 cases.add("post increment",
17621754 \\unsigned foo1(unsigned a) {
17631755 \\ a++;
17641756 \\ return a;
......@@ -1780,7 +1772,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17801772 \\}
17811773 });
17821774
1783 cases.add_2("deref function pointer",
1775 cases.add("deref function pointer",
17841776 \\void foo(void) {}
17851777 \\int baz(void) { return 0; }
17861778 \\void bar(void) {
......@@ -1810,7 +1802,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18101802 \\}
18111803 });
18121804
1813 cases.add_2("pre increment/decrement",
1805 cases.add("pre increment/decrement",
18141806 \\void foo(void) {
18151807 \\ int i = 0;
18161808 \\ unsigned u = 0;
......@@ -1854,7 +1846,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18541846 \\}
18551847 });
18561848
1857 cases.add_2("shift right assign",
1849 cases.add("shift right assign",
18581850 \\int log2(unsigned a) {
18591851 \\ int i = 0;
18601852 \\ while (a > 0) {
......@@ -1873,7 +1865,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18731865 \\}
18741866 });
18751867
1876 cases.add_2("shift right assign with a fixed size type",
1868 cases.add("shift right assign with a fixed size type",
18771869 \\#include <stdint.h>
18781870 \\int log2(uint32_t a) {
18791871 \\ int i = 0;
......@@ -1893,7 +1885,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18931885 \\}
18941886 });
18951887
1896 cases.add_2("compound assignment operators",
1888 cases.add("compound assignment operators",
18971889 \\void foo(void) {
18981890 \\ int a = 0;
18991891 \\ a += (a += 1);
......@@ -1951,7 +1943,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
19511943 \\}
19521944 });
19531945
1954 cases.add_2("compound assignment operators unsigned",
1946 cases.add("compound assignment operators unsigned",
19551947 \\void foo(void) {
19561948 \\ unsigned a = 0;
19571949 \\ a += (a += 1);
......@@ -2009,7 +2001,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20092001 \\}
20102002 });
20112003
2012 cases.add_2("post increment/decrement",
2004 cases.add("post increment/decrement",
20132005 \\void foo(void) {
20142006 \\ int i = 0;
20152007 \\ unsigned u = 0;
......@@ -2057,7 +2049,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20572049 \\}
20582050 });
20592051
2060 cases.add_2("implicit casts",
2052 cases.add("implicit casts",
20612053 \\#include <stdbool.h>
20622054 \\
20632055 \\void fn_int(int x);
......@@ -2113,7 +2105,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21132105 \\}
21142106 });
21152107
2116 cases.add_2("function call",
2108 cases.add("function call",
21172109 \\static void bar(void) { }
21182110 \\void foo(int *(baz)(void)) {
21192111 \\ bar();
......@@ -2128,7 +2120,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21282120 \\}
21292121 });
21302122
2131 cases.add_2("macro defines string literal with octal",
2123 cases.add("macro defines string literal with octal",
21322124 \\#define FOO "aoeu\023 derp"
21332125 \\#define FOO2 "aoeu\0234 derp"
21342126 \\#define FOO_CHAR '\077'
......@@ -2140,7 +2132,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21402132 \\pub const FOO_CHAR = '\x3f';
21412133 });
21422134
2143 cases.add_2("enums",
2135 cases.add("enums",
21442136 \\enum Foo {
21452137 \\ FooA,
21462138 \\ FooB,
......@@ -2162,7 +2154,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21622154 \\pub const Foo = enum_Foo;
21632155 });
21642156
2165 cases.add_2("enums",
2157 cases.add("enums",
21662158 \\enum Foo {
21672159 \\ FooA = 2,
21682160 \\ FooB = 5,
......@@ -2184,7 +2176,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21842176 \\pub const Foo = enum_Foo;
21852177 });
21862178
2187 cases.add_2("macro cast",
2179 cases.add("macro cast",
21882180 \\#define FOO(bar) baz((void *)(baz))
21892181 , &[_][]const u8{
21902182 \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeId(@TypeOf(baz)) == .Pointer) @ptrCast([*c]void, baz) else if (@typeId(@TypeOf(baz)) == .Int) @intToPtr([*c]void, baz) else @as([*c]void, baz))) {
......@@ -2192,1006 +2184,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21922184 \\}
21932185 });
21942186
2195 cases.add_2("macro conditional operator",
2187 cases.add("macro conditional operator",
21962188 \\#define FOO a ? b : c
21972189 , &[_][]const u8{
21982190 \\pub const FOO = if (a) b else c;
21992191 });
2200
2201 /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
2202 cases.addC("Parameterless function prototypes",
2203 \\void foo() {}
2204 \\void bar(void) {}
2205 , &[_][]const u8{
2206 \\pub export fn foo() void {}
2207 \\pub export fn bar() void {}
2208 });
2209
2210 cases.add("#define a char literal",
2211 \\#define A_CHAR 'a'
2212 , &[_][]const u8{
2213 \\pub const A_CHAR = 97;
2214 });
2215
2216 cases.add("generate inline func for #define global extern fn",
2217 \\extern void (*fn_ptr)(void);
2218 \\#define foo fn_ptr
2219 \\
2220 \\extern char (*fn_ptr2)(int, float);
2221 \\#define bar fn_ptr2
2222 , &[_][]const u8{
2223 \\pub extern var fn_ptr: ?extern fn () void;
2224 ,
2225 \\pub inline fn foo() void {
2226 \\ return fn_ptr.?();
2227 \\}
2228 ,
2229 \\pub extern var fn_ptr2: ?extern fn (c_int, f32) u8;
2230 ,
2231 \\pub inline fn bar(arg0: c_int, arg1: f32) u8 {
2232 \\ return fn_ptr2.?(arg0, arg1);
2233 \\}
2234 });
2235 cases.add("comment after integer literal",
2236 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2237 , &[_][]const u8{
2238 \\pub const SDL_INIT_VIDEO = 32;
2239 });
2240
2241 cases.add("u integer suffix after hex literal",
2242 \\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2243 , &[_][]const u8{
2244 \\pub const SDL_INIT_VIDEO = @as(c_uint, 32);
2245 });
2246
2247 cases.add("l integer suffix after hex literal",
2248 \\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2249 , &[_][]const u8{
2250 \\pub const SDL_INIT_VIDEO = @as(c_long, 32);
2251 });
2252
2253 cases.add("ul integer suffix after hex literal",
2254 \\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2255 , &[_][]const u8{
2256 \\pub const SDL_INIT_VIDEO = @as(c_ulong, 32);
2257 });
2258
2259 cases.add("lu integer suffix after hex literal",
2260 \\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2261 , &[_][]const u8{
2262 \\pub const SDL_INIT_VIDEO = @as(c_ulong, 32);
2263 });
2264
2265 cases.add("ll integer suffix after hex literal",
2266 \\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2267 , &[_][]const u8{
2268 \\pub const SDL_INIT_VIDEO = @as(c_longlong, 32);
2269 });
2270
2271 cases.add("ull integer suffix after hex literal",
2272 \\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2273 , &[_][]const u8{
2274 \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 32);
2275 });
2276
2277 cases.add("llu integer suffix after hex literal",
2278 \\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
2279 , &[_][]const u8{
2280 \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 32);
2281 });
2282
2283 cases.add("macros with field targets",
2284 \\typedef unsigned int GLbitfield;
2285 \\typedef void (*PFNGLCLEARPROC) (GLbitfield mask);
2286 \\typedef void(*OpenGLProc)(void);
2287 \\union OpenGLProcs {
2288 \\ OpenGLProc ptr[1];
2289 \\ struct {
2290 \\ PFNGLCLEARPROC Clear;
2291 \\ } gl;
2292 \\};
2293 \\extern union OpenGLProcs glProcs;
2294 \\#define glClearUnion glProcs.gl.Clear
2295 \\#define glClearPFN PFNGLCLEARPROC
2296 , &[_][]const u8{
2297 \\pub const GLbitfield = c_uint;
2298 ,
2299 \\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
2300 ,
2301 \\pub const OpenGLProc = ?extern fn () void;
2302 ,
2303 \\pub const union_OpenGLProcs = extern union {
2304 \\ ptr: [1]OpenGLProc,
2305 \\ gl: extern struct {
2306 \\ Clear: PFNGLCLEARPROC,
2307 \\ },
2308 \\};
2309 ,
2310 \\pub extern var glProcs: union_OpenGLProcs;
2311 ,
2312 \\pub const glClearPFN = PFNGLCLEARPROC;
2313 ,
2314 \\pub inline fn glClearUnion(arg0: GLbitfield) void {
2315 \\ return glProcs.gl.Clear.?(arg0);
2316 \\}
2317 ,
2318 \\pub const OpenGLProcs = union_OpenGLProcs;
2319 });
2320
2321 cases.add("macro pointer cast",
2322 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
2323 , &[_][]const u8{
2324 \\pub const NRF_GPIO = if (@typeId(@TypeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@TypeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
2325 });
2326
2327 cases.add("switch on int",
2328 \\int switch_fn(int i) {
2329 \\ int res = 0;
2330 \\ switch (i) {
2331 \\ case 0:
2332 \\ res = 1;
2333 \\ case 1:
2334 \\ res = 2;
2335 \\ default:
2336 \\ res = 3 * i;
2337 \\ break;
2338 \\ case 2:
2339 \\ res = 5;
2340 \\ }
2341 \\}
2342 , &[_][]const u8{
2343 \\pub fn switch_fn(i: c_int) c_int {
2344 \\ var res: c_int = 0;
2345 \\ __switch: {
2346 \\ __case_2: {
2347 \\ __default: {
2348 \\ __case_1: {
2349 \\ __case_0: {
2350 \\ switch (i) {
2351 \\ 0 => break :__case_0,
2352 \\ 1 => break :__case_1,
2353 \\ else => break :__default,
2354 \\ 2 => break :__case_2,
2355 \\ }
2356 \\ }
2357 \\ res = 1;
2358 \\ }
2359 \\ res = 2;
2360 \\ }
2361 \\ res = (3 * i);
2362 \\ break :__switch;
2363 \\ }
2364 \\ res = 5;
2365 \\ }
2366 \\}
2367 });
2368
2369 cases.add("for loop with var init but empty body",
2370 \\void foo(void) {
2371 \\ for (int x = 0; x < 10; x++);
2372 \\}
2373 , &[_][]const u8{
2374 \\pub fn foo() void {
2375 \\ {
2376 \\ var x: c_int = 0;
2377 \\ while (x < 10) : (x += 1) {}
2378 \\ }
2379 \\}
2380 });
2381
2382 cases.add("do while with empty body",
2383 \\void foo(void) {
2384 \\ do ; while (1);
2385 \\}
2386 , &[_][]const u8{ // TODO this should be if (1 != 0) break
2387 \\pub fn foo() void {
2388 \\ while (true) {
2389 \\ {}
2390 \\ if (!1) break;
2391 \\ }
2392 \\}
2393 });
2394
2395 cases.add("for with empty body",
2396 \\void foo(void) {
2397 \\ for (;;);
2398 \\}
2399 , &[_][]const u8{
2400 \\pub fn foo() void {
2401 \\ while (true) {}
2402 \\}
2403 });
2404
2405 cases.add("while with empty body",
2406 \\void foo(void) {
2407 \\ while (1);
2408 \\}
2409 , &[_][]const u8{
2410 \\pub fn foo() void {
2411 \\ while (1 != 0) {}
2412 \\}
2413 });
2414
2415 cases.add("undefined array global",
2416 \\int array[100];
2417 , &[_][]const u8{
2418 \\pub var array: [100]c_int = undefined;
2419 });
2420
2421 cases.add("qualified struct and enum",
2422 \\struct Foo {
2423 \\ int x;
2424 \\ int y;
2425 \\};
2426 \\enum Bar {
2427 \\ BarA,
2428 \\ BarB,
2429 \\};
2430 \\void func(struct Foo *a, enum Bar **b);
2431 , &[_][]const u8{
2432 \\pub const struct_Foo = extern struct {
2433 \\ x: c_int,
2434 \\ y: c_int,
2435 \\};
2436 ,
2437 \\pub const enum_Bar = extern enum {
2438 \\ A,
2439 \\ B,
2440 \\};
2441 ,
2442 \\pub const BarA = enum_Bar.A;
2443 ,
2444 \\pub const BarB = enum_Bar.B;
2445 ,
2446 \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
2447 ,
2448 \\pub const Foo = struct_Foo;
2449 ,
2450 \\pub const Bar = enum_Bar;
2451 });
2452
2453 cases.add("restrict -> noalias",
2454 \\void foo(void *restrict bar, void *restrict);
2455 , &[_][]const u8{
2456 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg1: ?*c_void) void;
2457 });
2458
2459 cases.addC("assign",
2460 \\int max(int a) {
2461 \\ int tmp;
2462 \\ tmp = a;
2463 \\ a = tmp;
2464 \\}
2465 , &[_][]const u8{
2466 \\pub export fn max(_arg_a: c_int) c_int {
2467 \\ var a = _arg_a;
2468 \\ var tmp: c_int = undefined;
2469 \\ tmp = a;
2470 \\ a = tmp;
2471 \\}
2472 });
2473
2474 cases.addC("chaining assign",
2475 \\void max(int a) {
2476 \\ int b, c;
2477 \\ c = b = a;
2478 \\}
2479 , &[_][]const u8{
2480 \\pub export fn max(a: c_int) void {
2481 \\ var b: c_int = undefined;
2482 \\ var c: c_int = undefined;
2483 \\ c = (x: {
2484 \\ const _tmp = a;
2485 \\ b = _tmp;
2486 \\ break :x _tmp;
2487 \\ });
2488 \\}
2489 });
2490
2491 cases.add("anonymous enum",
2492 \\enum {
2493 \\ One,
2494 \\ Two,
2495 \\};
2496 , &[_][]const u8{
2497 \\pub const One = 0;
2498 \\pub const Two = 1;
2499 });
2500
2501 cases.addC("c style cast",
2502 \\int float_to_int(float a) {
2503 \\ return (int)a;
2504 \\}
2505 , &[_][]const u8{
2506 \\pub export fn float_to_int(a: f32) c_int {
2507 \\ return @as(c_int, a);
2508 \\}
2509 });
2510
2511 cases.addC("comma operator",
2512 \\int foo(void) {
2513 \\ return 1, 2;
2514 \\}
2515 , &[_][]const u8{
2516 \\pub export fn foo() c_int {
2517 \\ return x: {
2518 \\ _ = 1;
2519 \\ break :x 2;
2520 \\ };
2521 \\}
2522 });
2523
2524 cases.addC("escape sequences",
2525 \\const char *escapes() {
2526 \\char a = '\'',
2527 \\ b = '\\',
2528 \\ c = '\a',
2529 \\ d = '\b',
2530 \\ e = '\f',
2531 \\ f = '\n',
2532 \\ g = '\r',
2533 \\ h = '\t',
2534 \\ i = '\v',
2535 \\ j = '\0',
2536 \\ k = '\"';
2537 \\ return "\'\\\a\b\f\n\r\t\v\0\"";
2538 \\}
2539 \\
2540 , &[_][]const u8{
2541 \\pub export fn escapes() [*c]const u8 {
2542 \\ var a: u8 = @as(u8, '\'');
2543 \\ var b: u8 = @as(u8, '\\');
2544 \\ var c: u8 = @as(u8, '\x07');
2545 \\ var d: u8 = @as(u8, '\x08');
2546 \\ var e: u8 = @as(u8, '\x0c');
2547 \\ var f: u8 = @as(u8, '\n');
2548 \\ var g: u8 = @as(u8, '\r');
2549 \\ var h: u8 = @as(u8, '\t');
2550 \\ var i: u8 = @as(u8, '\x0b');
2551 \\ var j: u8 = @as(u8, '\x00');
2552 \\ var k: u8 = @as(u8, '\"');
2553 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
2554 \\}
2555 \\
2556 });
2557
2558 cases.addC("do loop",
2559 \\void foo(void) {
2560 \\ int a = 2;
2561 \\ do {
2562 \\ a--;
2563 \\ } while (a != 0);
2564 \\
2565 \\ int b = 2;
2566 \\ do
2567 \\ b--;
2568 \\ while (b != 0);
2569 \\}
2570 , &[_][]const u8{
2571 \\pub export fn foo() void {
2572 \\ var a: c_int = 2;
2573 \\ while (true) {
2574 \\ a -= 1;
2575 \\ if (!(a != 0)) break;
2576 \\ }
2577 \\ var b: c_int = 2;
2578 \\ while (true) {
2579 \\ b -= 1;
2580 \\ if (!(b != 0)) break;
2581 \\ }
2582 \\}
2583 });
2584
2585 cases.addC("==, !=",
2586 \\int max(int a, int b) {
2587 \\ if (a == b)
2588 \\ return a;
2589 \\ if (a != b)
2590 \\ return b;
2591 \\ return a;
2592 \\}
2593 , &[_][]const u8{
2594 \\pub export fn max(a: c_int, b: c_int) c_int {
2595 \\ if (a == b) return a;
2596 \\ if (a != b) return b;
2597 \\ return a;
2598 \\}
2599 });
2600
2601 cases.addC("bitwise binary operators",
2602 \\int max(int a, int b) {
2603 \\ return (a & b) ^ (a | b);
2604 \\}
2605 , &[_][]const u8{
2606 \\pub export fn max(a: c_int, b: c_int) c_int {
2607 \\ return (a & b) ^ (a | b);
2608 \\}
2609 });
2610
2611 cases.addC("statement expression",
2612 \\int foo(void) {
2613 \\ return ({
2614 \\ int a = 1;
2615 \\ a;
2616 \\ });
2617 \\}
2618 , &[_][]const u8{
2619 \\pub export fn foo() c_int {
2620 \\ return x: {
2621 \\ var a: c_int = 1;
2622 \\ break :x a;
2623 \\ };
2624 \\}
2625 });
2626
2627 cases.addC("field access expression",
2628 \\struct Foo {
2629 \\ int field;
2630 \\};
2631 \\int read_field(struct Foo *foo) {
2632 \\ return foo->field;
2633 \\}
2634 , &[_][]const u8{
2635 \\pub const struct_Foo = extern struct {
2636 \\ field: c_int,
2637 \\};
2638 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
2639 \\ return foo.*.field;
2640 \\}
2641 });
2642
2643 cases.addC("array access",
2644 \\int array[100];
2645 \\int foo(int index) {
2646 \\ return array[index];
2647 \\}
2648 , &[_][]const u8{
2649 \\pub var array: [100]c_int = undefined;
2650 \\pub export fn foo(index: c_int) c_int {
2651 \\ return array[index];
2652 \\}
2653 });
2654
2655 cases.addC("logical and, logical or",
2656 \\int max(int a, int b) {
2657 \\ if (a < b || a == b)
2658 \\ return b;
2659 \\ if (a >= b && a == b)
2660 \\ return a;
2661 \\ return a;
2662 \\}
2663 , &[_][]const u8{
2664 \\pub export fn max(a: c_int, b: c_int) c_int {
2665 \\ if ((a < b) or (a == b)) return b;
2666 \\ if ((a >= b) and (a == b)) return a;
2667 \\ return a;
2668 \\}
2669 });
2670
2671 cases.addC("if statement",
2672 \\int max(int a, int b) {
2673 \\ if (a < b)
2674 \\ return b;
2675 \\
2676 \\ if (a < b)
2677 \\ return b;
2678 \\ else
2679 \\ return a;
2680 \\
2681 \\ if (a < b) ; else ;
2682 \\}
2683 , &[_][]const u8{
2684 \\pub export fn max(a: c_int, b: c_int) c_int {
2685 \\ if (a < b) return b;
2686 \\ if (a < b) return b else return a;
2687 \\ if (a < b) {} else {}
2688 \\}
2689 });
2690
2691 cases.add("variable name shadowing",
2692 \\int foo(void) {
2693 \\ int x = 1;
2694 \\ {
2695 \\ int x = 2;
2696 \\ x += 1;
2697 \\ }
2698 \\ return x;
2699 \\}
2700 , &[_][]const u8{
2701 \\pub fn foo() c_int {
2702 \\ var x: c_int = 1;
2703 \\ {
2704 \\ var x_0: c_int = 2;
2705 \\ x_0 += 1;
2706 \\ }
2707 \\ return x;
2708 \\}
2709 });
2710
2711 cases.add("if on non-bool",
2712 \\enum SomeEnum { A, B, C };
2713 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
2714 \\ if (a) return 0;
2715 \\ if (b) return 1;
2716 \\ if (c) return 2;
2717 \\ if (d) return 3;
2718 \\ return 4;
2719 \\}
2720 , &[_][]const u8{
2721 \\pub const A = enum_SomeEnum.A;
2722 \\pub const B = enum_SomeEnum.B;
2723 \\pub const C = enum_SomeEnum.C;
2724 \\pub const enum_SomeEnum = extern enum {
2725 \\ A,
2726 \\ B,
2727 \\ C,
2728 \\};
2729 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
2730 \\ if (a != 0) return 0;
2731 \\ if (b != 0) return 1;
2732 \\ if (c != null) return 2;
2733 \\ if (d != @bitCast(enum_SomeEnum, @as(@TagType(enum_SomeEnum), 0))) return 3;
2734 \\ return 4;
2735 \\}
2736 });
2737
2738 cases.addAllowWarnings("simple data types",
2739 \\#include <stdint.h>
2740 \\int foo(char a, unsigned char b, signed char c);
2741 \\int foo(char a, unsigned char b, signed char c); // test a duplicate prototype
2742 \\void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
2743 \\void baz(int8_t a, int16_t b, int32_t c, int64_t d);
2744 , &[_][]const u8{
2745 \\pub extern fn foo(a: u8, b: u8, c: i8) c_int;
2746 ,
2747 \\pub extern fn bar(a: u8, b: u16, c: u32, d: u64) void;
2748 ,
2749 \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
2750 });
2751
2752 cases.addC("simple function",
2753 \\int abs(int a) {
2754 \\ return a < 0 ? -a : a;
2755 \\}
2756 , &[_][]const u8{
2757 \\pub export fn abs(a: c_int) c_int {
2758 \\ return if (a < 0) -a else a;
2759 \\}
2760 });
2761
2762 cases.addC("post increment",
2763 \\unsigned foo1(unsigned a) {
2764 \\ a++;
2765 \\ return a;
2766 \\}
2767 \\int foo2(int a) {
2768 \\ a++;
2769 \\ return a;
2770 \\}
2771 , &[_][]const u8{
2772 \\pub export fn foo1(_arg_a: c_uint) c_uint {
2773 \\ var a = _arg_a;
2774 \\ a +%= 1;
2775 \\ return a;
2776 \\}
2777 \\pub export fn foo2(_arg_a: c_int) c_int {
2778 \\ var a = _arg_a;
2779 \\ a += 1;
2780 \\ return a;
2781 \\}
2782 });
2783
2784 cases.addC("deref function pointer",
2785 \\void foo(void) {}
2786 \\int baz(void) { return 0; }
2787 \\void bar(void) {
2788 \\ void(*f)(void) = foo;
2789 \\ int(*b)(void) = baz;
2790 \\ f();
2791 \\ (*(f))();
2792 \\ foo();
2793 \\ b();
2794 \\ (*(b))();
2795 \\ baz();
2796 \\}
2797 , &[_][]const u8{
2798 \\pub export fn foo() void {}
2799 \\pub export fn baz() c_int {
2800 \\ return 0;
2801 \\}
2802 \\pub export fn bar() void {
2803 \\ var f: ?extern fn () void = foo;
2804 \\ var b: ?extern fn () c_int = baz;
2805 \\ f.?();
2806 \\ f.?();
2807 \\ foo();
2808 \\ _ = b.?();
2809 \\ _ = b.?();
2810 \\ _ = baz();
2811 \\}
2812 });
2813
2814 cases.addC("pre increment/decrement",
2815 \\void foo(void) {
2816 \\ int i = 0;
2817 \\ unsigned u = 0;
2818 \\ ++i;
2819 \\ --i;
2820 \\ ++u;
2821 \\ --u;
2822 \\ i = ++i;
2823 \\ i = --i;
2824 \\ u = ++u;
2825 \\ u = --u;
2826 \\}
2827 , &[_][]const u8{
2828 \\pub export fn foo() void {
2829 \\ var i: c_int = 0;
2830 \\ var u: c_uint = @as(c_uint, 0);
2831 \\ i += 1;
2832 \\ i -= 1;
2833 \\ u +%= 1;
2834 \\ u -%= 1;
2835 \\ i = (x: {
2836 \\ const _ref = &i;
2837 \\ _ref.* += 1;
2838 \\ break :x _ref.*;
2839 \\ });
2840 \\ i = (x: {
2841 \\ const _ref = &i;
2842 \\ _ref.* -= 1;
2843 \\ break :x _ref.*;
2844 \\ });
2845 \\ u = (x: {
2846 \\ const _ref = &u;
2847 \\ _ref.* +%= 1;
2848 \\ break :x _ref.*;
2849 \\ });
2850 \\ u = (x: {
2851 \\ const _ref = &u;
2852 \\ _ref.* -%= 1;
2853 \\ break :x _ref.*;
2854 \\ });
2855 \\}
2856 });
2857
2858 cases.addC("shift right assign",
2859 \\int log2(unsigned a) {
2860 \\ int i = 0;
2861 \\ while (a > 0) {
2862 \\ a >>= 1;
2863 \\ }
2864 \\ return i;
2865 \\}
2866 , &[_][]const u8{
2867 \\pub export fn log2(_arg_a: c_uint) c_int {
2868 \\ var a = _arg_a;
2869 \\ var i: c_int = 0;
2870 \\ while (a > @as(c_uint, 0)) {
2871 \\ a >>= @as(@import("std").math.Log2Int(c_uint), 1);
2872 \\ }
2873 \\ return i;
2874 \\}
2875 });
2876
2877 cases.addC("shift right assign with a fixed size type",
2878 \\#include <stdint.h>
2879 \\int log2(uint32_t a) {
2880 \\ int i = 0;
2881 \\ while (a > 0) {
2882 \\ a >>= 1;
2883 \\ }
2884 \\ return i;
2885 \\}
2886 , &[_][]const u8{
2887 \\pub export fn log2(_arg_a: u32) c_int {
2888 \\ var a = _arg_a;
2889 \\ var i: c_int = 0;
2890 \\ while (a > @as(c_uint, 0)) {
2891 \\ a >>= @as(u5, 1);
2892 \\ }
2893 \\ return i;
2894 \\}
2895 });
2896
2897 cases.addC("compound assignment operators",
2898 \\void foo(void) {
2899 \\ int a = 0;
2900 \\ a += (a += 1);
2901 \\ a -= (a -= 1);
2902 \\ a *= (a *= 1);
2903 \\ a &= (a &= 1);
2904 \\ a |= (a |= 1);
2905 \\ a ^= (a ^= 1);
2906 \\ a >>= (a >>= 1);
2907 \\ a <<= (a <<= 1);
2908 \\}
2909 , &[_][]const u8{
2910 \\pub export fn foo() void {
2911 \\ var a: c_int = 0;
2912 \\ a += (x: {
2913 \\ const _ref = &a;
2914 \\ _ref.* = (_ref.* + 1);
2915 \\ break :x _ref.*;
2916 \\ });
2917 \\ a -= (x: {
2918 \\ const _ref = &a;
2919 \\ _ref.* = (_ref.* - 1);
2920 \\ break :x _ref.*;
2921 \\ });
2922 \\ a *= (x: {
2923 \\ const _ref = &a;
2924 \\ _ref.* = (_ref.* * 1);
2925 \\ break :x _ref.*;
2926 \\ });
2927 \\ a &= (x: {
2928 \\ const _ref = &a;
2929 \\ _ref.* = (_ref.* & 1);
2930 \\ break :x _ref.*;
2931 \\ });
2932 \\ a |= (x: {
2933 \\ const _ref = &a;
2934 \\ _ref.* = (_ref.* | 1);
2935 \\ break :x _ref.*;
2936 \\ });
2937 \\ a ^= (x: {
2938 \\ const _ref = &a;
2939 \\ _ref.* = (_ref.* ^ 1);
2940 \\ break :x _ref.*;
2941 \\ });
2942 \\ a >>= @as(@import("std").math.Log2Int(c_int), (x: {
2943 \\ const _ref = &a;
2944 \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_int), 1));
2945 \\ break :x _ref.*;
2946 \\ }));
2947 \\ a <<= @as(@import("std").math.Log2Int(c_int), (x: {
2948 \\ const _ref = &a;
2949 \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_int), 1));
2950 \\ break :x _ref.*;
2951 \\ }));
2952 \\}
2953 });
2954
2955 cases.addC("compound assignment operators unsigned",
2956 \\void foo(void) {
2957 \\ unsigned a = 0;
2958 \\ a += (a += 1);
2959 \\ a -= (a -= 1);
2960 \\ a *= (a *= 1);
2961 \\ a &= (a &= 1);
2962 \\ a |= (a |= 1);
2963 \\ a ^= (a ^= 1);
2964 \\ a >>= (a >>= 1);
2965 \\ a <<= (a <<= 1);
2966 \\}
2967 , &[_][]const u8{
2968 \\pub export fn foo() void {
2969 \\ var a: c_uint = @as(c_uint, 0);
2970 \\ a +%= (x: {
2971 \\ const _ref = &a;
2972 \\ _ref.* = (_ref.* +% @as(c_uint, 1));
2973 \\ break :x _ref.*;
2974 \\ });
2975 \\ a -%= (x: {
2976 \\ const _ref = &a;
2977 \\ _ref.* = (_ref.* -% @as(c_uint, 1));
2978 \\ break :x _ref.*;
2979 \\ });
2980 \\ a *%= (x: {
2981 \\ const _ref = &a;
2982 \\ _ref.* = (_ref.* *% @as(c_uint, 1));
2983 \\ break :x _ref.*;
2984 \\ });
2985 \\ a &= (x: {
2986 \\ const _ref = &a;
2987 \\ _ref.* = (_ref.* & @as(c_uint, 1));
2988 \\ break :x _ref.*;
2989 \\ });
2990 \\ a |= (x: {
2991 \\ const _ref = &a;
2992 \\ _ref.* = (_ref.* | @as(c_uint, 1));
2993 \\ break :x _ref.*;
2994 \\ });
2995 \\ a ^= (x: {
2996 \\ const _ref = &a;
2997 \\ _ref.* = (_ref.* ^ @as(c_uint, 1));
2998 \\ break :x _ref.*;
2999 \\ });
3000 \\ a >>= @as(@import("std").math.Log2Int(c_uint), (x: {
3001 \\ const _ref = &a;
3002 \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_uint), 1));
3003 \\ break :x _ref.*;
3004 \\ }));
3005 \\ a <<= @as(@import("std").math.Log2Int(c_uint), (x: {
3006 \\ const _ref = &a;
3007 \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_uint), 1));
3008 \\ break :x _ref.*;
3009 \\ }));
3010 \\}
3011 });
3012
3013 cases.addC("post increment/decrement",
3014 \\void foo(void) {
3015 \\ int i = 0;
3016 \\ unsigned u = 0;
3017 \\ i++;
3018 \\ i--;
3019 \\ u++;
3020 \\ u--;
3021 \\ i = i++;
3022 \\ i = i--;
3023 \\ u = u++;
3024 \\ u = u--;
3025 \\}
3026 , &[_][]const u8{
3027 \\pub export fn foo() void {
3028 \\ var i: c_int = 0;
3029 \\ var u: c_uint = @as(c_uint, 0);
3030 \\ i += 1;
3031 \\ i -= 1;
3032 \\ u +%= 1;
3033 \\ u -%= 1;
3034 \\ i = (x: {
3035 \\ const _ref = &i;
3036 \\ const _tmp = _ref.*;
3037 \\ _ref.* += 1;
3038 \\ break :x _tmp;
3039 \\ });
3040 \\ i = (x: {
3041 \\ const _ref = &i;
3042 \\ const _tmp = _ref.*;
3043 \\ _ref.* -= 1;
3044 \\ break :x _tmp;
3045 \\ });
3046 \\ u = (x: {
3047 \\ const _ref = &u;
3048 \\ const _tmp = _ref.*;
3049 \\ _ref.* +%= 1;
3050 \\ break :x _tmp;
3051 \\ });
3052 \\ u = (x: {
3053 \\ const _ref = &u;
3054 \\ const _tmp = _ref.*;
3055 \\ _ref.* -%= 1;
3056 \\ break :x _tmp;
3057 \\ });
3058 \\}
3059 });
3060
3061 cases.addC("implicit casts",
3062 \\#include <stdbool.h>
3063 \\
3064 \\void fn_int(int x);
3065 \\void fn_f32(float x);
3066 \\void fn_f64(double x);
3067 \\void fn_char(char x);
3068 \\void fn_bool(bool x);
3069 \\void fn_ptr(void *x);
3070 \\
3071 \\void call(int q) {
3072 \\ fn_int(3.0f);
3073 \\ fn_int(3.0);
3074 \\ fn_int(3.0L);
3075 \\ fn_int('ABCD');
3076 \\ fn_f32(3);
3077 \\ fn_f64(3);
3078 \\ fn_char('3');
3079 \\ fn_char('\x1');
3080 \\ fn_char(0);
3081 \\ fn_f32(3.0f);
3082 \\ fn_f64(3.0);
3083 \\ fn_bool(123);
3084 \\ fn_bool(0);
3085 \\ fn_bool(&fn_int);
3086 \\ fn_int(&fn_int);
3087 \\ fn_ptr(42);
3088 \\}
3089 , &[_][]const u8{
3090 \\pub extern fn fn_int(x: c_int) void;
3091 \\pub extern fn fn_f32(x: f32) void;
3092 \\pub extern fn fn_f64(x: f64) void;
3093 \\pub extern fn fn_char(x: u8) void;
3094 \\pub extern fn fn_bool(x: bool) void;
3095 \\pub extern fn fn_ptr(x: ?*c_void) void;
3096 \\pub export fn call(q: c_int) void {
3097 \\ fn_int(@floatToInt(c_int, 3.000000));
3098 \\ fn_int(@floatToInt(c_int, 3.000000));
3099 \\ fn_int(@floatToInt(c_int, 3.000000));
3100 \\ fn_int(1094861636);
3101 \\ fn_f32(@intToFloat(f32, 3));
3102 \\ fn_f64(@intToFloat(f64, 3));
3103 \\ fn_char(@as(u8, '3'));
3104 \\ fn_char(@as(u8, '\x01'));
3105 \\ fn_char(@as(u8, 0));
3106 \\ fn_f32(3.000000);
3107 \\ fn_f64(3.000000);
3108 \\ fn_bool(true);
3109 \\ fn_bool(false);
3110 \\ fn_bool(@ptrToInt(&fn_int) != 0);
3111 \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
3112 \\ fn_ptr(@intToPtr(?*c_void, 42));
3113 \\}
3114 });
3115
3116 cases.addC("function call",
3117 \\static void bar(void) { }
3118 \\void foo(int *(baz)(void)) {
3119 \\ bar();
3120 \\ baz();
3121 \\}
3122 , &[_][]const u8{
3123 \\pub fn bar() void {}
3124 \\pub export fn foo(baz: ?extern fn () [*c]c_int) void {
3125 \\ bar();
3126 \\ _ = baz.?();
3127 \\}
3128 });
3129
3130 cases.add("macro defines string literal with hex",
3131 \\#define FOO "aoeu\xab derp"
3132 \\#define FOO2 "aoeu\x0007a derp"
3133 \\#define FOO_CHAR '\xfF'
3134 , &[_][]const u8{
3135 \\pub const FOO = "aoeu\xab derp";
3136 ,
3137 \\pub const FOO2 = "aoeuz derp";
3138 ,
3139 \\pub const FOO_CHAR = 255;
3140 });
3141
3142 cases.add("macro defines string literal with octal",
3143 \\#define FOO "aoeu\023 derp"
3144 \\#define FOO2 "aoeu\0234 derp"
3145 \\#define FOO_CHAR '\077'
3146 , &[_][]const u8{
3147 \\pub const FOO = "aoeu\x13 derp";
3148 ,
3149 \\pub const FOO2 = "aoeu\x134 derp";
3150 ,
3151 \\pub const FOO_CHAR = 63;
3152 });
3153
3154 cases.add("enums",
3155 \\enum Foo {
3156 \\ FooA,
3157 \\ FooB,
3158 \\ Foo1,
3159 \\};
3160 , &[_][]const u8{
3161 \\pub const enum_Foo = extern enum {
3162 \\ A,
3163 \\ B,
3164 \\ @"1",
3165 \\};
3166 ,
3167 \\pub const FooA = enum_Foo.A;
3168 ,
3169 \\pub const FooB = enum_Foo.B;
3170 ,
3171 \\pub const Foo1 = enum_Foo.@"1";
3172 ,
3173 \\pub const Foo = enum_Foo;
3174 });
3175
3176 cases.add("enums",
3177 \\enum Foo {
3178 \\ FooA = 2,
3179 \\ FooB = 5,
3180 \\ Foo1,
3181 \\};
3182 , &[_][]const u8{
3183 \\pub const enum_Foo = extern enum {
3184 \\ A = 2,
3185 \\ B = 5,
3186 \\ @"1" = 6,
3187 \\};
3188 ,
3189 \\pub const FooA = enum_Foo.A;
3190 ,
3191 \\pub const FooB = enum_Foo.B;
3192 ,
3193 \\pub const Foo1 = enum_Foo.@"1";
3194 ,
3195 \\pub const Foo = enum_Foo;
3196 });
31972192}