authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-01 22:46:46-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-01-01 22:46:46-05:00
log576320e6d5bf706a0ee03a3e9318c8ef2fd6e76f
tree0405ebde5048781fd6f65d3bf9d444c54d04bd02
parent1b64a5f5f0cece3cf0009410ddb13b5dd6f899e1
parent88c5e2a96e09270a2ec3045639e7cab3712f5291
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4025 from ziglang/Vexu-stage-2-cimport

Use self hosted translate-c for cImport

27 files changed, 1388 insertions(+), 7943 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)
lib/std/crypto/chacha20.zig+1-1
......@@ -224,7 +224,7 @@ test "crypto.chacha20 test vector sunscreen" {
224224 // Chacha20 is self-reversing.
225225 var plaintext: [114]u8 = undefined;
226226 chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);
227 testing.expect(mem.compare(u8, input, &plaintext) == mem.Compare.Equal);
227 testing.expect(mem.order(u8, input, &plaintext) == .eq);
228228}
229229
230230// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
lib/std/http/headers.zig+2-2
......@@ -70,12 +70,12 @@ const HeaderEntry = struct {
7070 }
7171
7272 // Sort lexicographically on header name
73 return mem.compare(u8, a.name, b.name) == mem.Compare.LessThan;
73 return mem.order(u8, a.name, b.name) == .lt;
7474 }
7575
7676 // Sort lexicographically on header value
7777 if (!mem.eql(u8, a.value, b.value)) {
78 return mem.compare(u8, a.value, b.value) == mem.Compare.LessThan;
78 return mem.order(u8, a.value, b.value) == .lt;
7979 }
8080
8181 // Doesn't matter here; need to pick something for sort consistency
lib/std/math.zig+27-5
......@@ -926,9 +926,6 @@ test "minInt and maxInt" {
926926}
927927
928928test "max value type" {
929 // If the type of maxInt(i32) was i32 then this implicit cast to
930 // u32 would not work. But since the value is a number literal,
931 // it works fine.
932929 const x: u32 = maxInt(i32);
933930 testing.expect(x == 2147483647);
934931}
......@@ -944,7 +941,32 @@ test "math.mulWide" {
944941 testing.expect(mulWide(u8, 100, 100) == 10000);
945942}
946943
947/// Not to be confused with `std.mem.Compare`.
944/// See also `CompareOperator`.
945pub const Order = enum {
946 /// Less than (`<`)
947 lt,
948
949 /// Equal (`==`)
950 eq,
951
952 /// Greater than (`>`)
953 gt,
954};
955
956/// Given two numbers, this function returns the order they are with respect to each other.
957pub fn order(a: var, b: var) Order {
958 if (a == b) {
959 return .eq;
960 } else if (a < b) {
961 return .lt;
962 } else if (a > b) {
963 return .gt;
964 } else {
965 unreachable;
966 }
967}
968
969/// See also `Order`.
948970pub const CompareOperator = enum {
949971 /// Less than (`<`)
950972 lt,
......@@ -979,7 +1001,7 @@ pub fn compare(a: var, op: CompareOperator, b: var) bool {
9791001 };
9801002}
9811003
982test "math.lt, et al < <= > >= between signed and unsigned" {
1004test "compare between signed and unsigned" {
9831005 testing.expect(compare(@as(i8, -1), .lt, @as(u8, 255)));
9841006 testing.expect(compare(@as(i8, 2), .gt, @as(u8, 1)));
9851007 testing.expect(!compare(@as(i8, -1), .gte, @as(u8, 255)));
lib/std/mem.zig+13-35
......@@ -239,12 +239,6 @@ pub const Allocator = struct {
239239 }
240240};
241241
242pub const Compare = enum {
243 LessThan,
244 Equal,
245 GreaterThan,
246};
247
248242/// Copy all of source into dest at position 0.
249243/// dest.len must be >= source.len.
250244/// dest.ptr must be <= src.ptr.
......@@ -297,46 +291,30 @@ test "mem.secureZero" {
297291 testing.expectEqualSlices(u8, a[0..], b[0..]);
298292}
299293
300pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
294pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order {
301295 const n = math.min(lhs.len, rhs.len);
302296 var i: usize = 0;
303297 while (i < n) : (i += 1) {
304 if (lhs[i] == rhs[i]) {
305 continue;
306 } else if (lhs[i] < rhs[i]) {
307 return Compare.LessThan;
308 } else if (lhs[i] > rhs[i]) {
309 return Compare.GreaterThan;
310 } else {
311 unreachable;
298 switch (math.order(lhs[i], rhs[i])) {
299 .eq => continue,
300 .lt => return .lt,
301 .gt => return .gt,
312302 }
313303 }
314
315 if (lhs.len == rhs.len) {
316 return Compare.Equal;
317 } else if (lhs.len < rhs.len) {
318 return Compare.LessThan;
319 } else if (lhs.len > rhs.len) {
320 return Compare.GreaterThan;
321 }
322 unreachable;
304 return math.order(lhs.len, rhs.len);
323305}
324306
325test "mem.compare" {
326 testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan);
327 testing.expect(compare(u8, "abc", "abc") == Compare.Equal);
328 testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan);
329 testing.expect(compare(u8, "", "") == Compare.Equal);
330 testing.expect(compare(u8, "", "a") == Compare.LessThan);
307test "order" {
308 testing.expect(order(u8, "abcd", "bee") == .lt);
309 testing.expect(order(u8, "abc", "abc") == .eq);
310 testing.expect(order(u8, "abc", "abc0") == .lt);
311 testing.expect(order(u8, "", "") == .eq);
312 testing.expect(order(u8, "", "a") == .lt);
331313}
332314
333315/// Returns true if lhs < rhs, false otherwise
334316pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
335 var result = compare(T, lhs, rhs);
336 if (result == Compare.LessThan) {
337 return true;
338 } else
339 return false;
317 return order(T, lhs, rhs) == .lt;
340318}
341319
342320test "mem.lessThan" {
lib/std/rb.zig+20-18
......@@ -1,7 +1,7 @@
11const std = @import("std.zig");
22const assert = std.debug.assert;
33const testing = std.testing;
4const mem = std.mem; // For mem.Compare
4const Order = std.math.Order;
55
66const Color = enum(u1) {
77 Black,
......@@ -132,7 +132,7 @@ pub const Node = struct {
132132
133133pub const Tree = struct {
134134 root: ?*Node,
135 compareFn: fn (*Node, *Node) mem.Compare,
135 compareFn: fn (*Node, *Node) Order,
136136
137137 /// If you have a need for a version that caches this, please file a bug.
138138 pub fn first(tree: *Tree) ?*Node {
......@@ -389,7 +389,7 @@ pub const Tree = struct {
389389 var new = newconst;
390390
391391 // I assume this can get optimized out if the caller already knows.
392 if (tree.compareFn(old, new) != mem.Compare.Equal) return ReplaceError.NotEqual;
392 if (tree.compareFn(old, new) != .eq) return ReplaceError.NotEqual;
393393
394394 if (old.getParent()) |parent| {
395395 parent.setChild(new, parent.left == old);
......@@ -404,7 +404,7 @@ pub const Tree = struct {
404404 new.* = old.*;
405405 }
406406
407 pub fn init(tree: *Tree, f: fn (*Node, *Node) mem.Compare) void {
407 pub fn init(tree: *Tree, f: fn (*Node, *Node) Order) void {
408408 tree.root = null;
409409 tree.compareFn = f;
410410 }
......@@ -469,19 +469,21 @@ fn doLookup(key: *Node, tree: *Tree, pparent: *?*Node, is_left: *bool) ?*Node {
469469 is_left.* = false;
470470
471471 while (maybe_node) |node| {
472 var res: mem.Compare = tree.compareFn(node, key);
473 if (res == mem.Compare.Equal) {
472 const res = tree.compareFn(node, key);
473 if (res == .eq) {
474474 return node;
475475 }
476476 pparent.* = node;
477 if (res == mem.Compare.GreaterThan) {
478 is_left.* = true;
479 maybe_node = node.left;
480 } else if (res == mem.Compare.LessThan) {
481 is_left.* = false;
482 maybe_node = node.right;
483 } else {
484 unreachable;
477 switch (res) {
478 .gt => {
479 is_left.* = true;
480 maybe_node = node.left;
481 },
482 .lt => {
483 is_left.* = false;
484 maybe_node = node.right;
485 },
486 .eq => unreachable, // handled above
485487 }
486488 }
487489 return null;
......@@ -496,16 +498,16 @@ fn testGetNumber(node: *Node) *testNumber {
496498 return @fieldParentPtr(testNumber, "node", node);
497499}
498500
499fn testCompare(l: *Node, r: *Node) mem.Compare {
501fn testCompare(l: *Node, r: *Node) Order {
500502 var left = testGetNumber(l);
501503 var right = testGetNumber(r);
502504
503505 if (left.value < right.value) {
504 return mem.Compare.LessThan;
506 return .lt;
505507 } else if (left.value == right.value) {
506 return mem.Compare.Equal;
508 return .eq;
507509 } else if (left.value > right.value) {
508 return mem.Compare.GreaterThan;
510 return .gt;
509511 }
510512 unreachable;
511513}
lib/std/zig/ast.zig+49-46
......@@ -13,6 +13,7 @@ pub const Tree = struct {
1313 root_node: *Node.Root,
1414 arena_allocator: std.heap.ArenaAllocator,
1515 errors: ErrorList,
16 generated: bool = false,
1617
1718 pub const TokenList = SegmentedList(Token, 64);
1819 pub const ErrorList = SegmentedList(Error, 0);
......@@ -58,6 +59,8 @@ pub const Tree = struct {
5859 .line_start = start_index,
5960 .line_end = self.source.len,
6061 };
62 if (self.generated)
63 return loc;
6164 const token_start = token.start;
6265 for (self.source[start_index..]) |c, i| {
6366 if (i + start_index == token_start) {
......@@ -581,7 +584,7 @@ pub const Node = struct {
581584 }
582585
583586 pub const Root = struct {
584 base: Node = Node {.id = .Root},
587 base: Node = Node{ .id = .Root },
585588 decls: DeclList,
586589 eof_token: TokenIndex,
587590
......@@ -604,7 +607,7 @@ pub const Node = struct {
604607 };
605608
606609 pub const VarDecl = struct {
607 base: Node = Node {.id = .VarDecl},
610 base: Node = Node{ .id = .VarDecl },
608611 doc_comments: ?*DocComment,
609612 visib_token: ?TokenIndex,
610613 thread_local_token: ?TokenIndex,
......@@ -661,7 +664,7 @@ pub const Node = struct {
661664 };
662665
663666 pub const Use = struct {
664 base: Node = Node {.id = .Use},
667 base: Node = Node{ .id = .Use },
665668 doc_comments: ?*DocComment,
666669 visib_token: ?TokenIndex,
667670 use_token: TokenIndex,
......@@ -688,7 +691,7 @@ pub const Node = struct {
688691 };
689692
690693 pub const ErrorSetDecl = struct {
691 base: Node = Node {.id = .ErrorSetDecl},
694 base: Node = Node{ .id = .ErrorSetDecl },
692695 error_token: TokenIndex,
693696 decls: DeclList,
694697 rbrace_token: TokenIndex,
......@@ -714,7 +717,7 @@ pub const Node = struct {
714717 };
715718
716719 pub const ContainerDecl = struct {
717 base: Node = Node {.id = .ContainerDecl},
720 base: Node = Node{ .id = .ContainerDecl },
718721 layout_token: ?TokenIndex,
719722 kind_token: TokenIndex,
720723 init_arg_expr: InitArg,
......@@ -801,7 +804,7 @@ pub const Node = struct {
801804 };
802805
803806 pub const ErrorTag = struct {
804 base: Node = Node {.id = .ErrorTag},
807 base: Node = Node{ .id = .ErrorTag },
805808 doc_comments: ?*DocComment,
806809 name_token: TokenIndex,
807810
......@@ -826,7 +829,7 @@ pub const Node = struct {
826829 };
827830
828831 pub const Identifier = struct {
829 base: Node = Node {.id = .Identifier},
832 base: Node = Node{ .id = .Identifier },
830833 token: TokenIndex,
831834
832835 pub fn iterate(self: *Identifier, index: usize) ?*Node {
......@@ -843,7 +846,7 @@ pub const Node = struct {
843846 };
844847
845848 pub const FnProto = struct {
846 base: Node = Node {.id = .FnProto},
849 base: Node = Node{ .id = .FnProto },
847850 doc_comments: ?*DocComment,
848851 visib_token: ?TokenIndex,
849852 fn_token: TokenIndex,
......@@ -925,7 +928,7 @@ pub const Node = struct {
925928 };
926929
927930 pub const AnyFrameType = struct {
928 base: Node = Node {.id = .AnyFrameType},
931 base: Node = Node{ .id = .AnyFrameType },
929932 anyframe_token: TokenIndex,
930933 result: ?Result,
931934
......@@ -956,7 +959,7 @@ pub const Node = struct {
956959 };
957960
958961 pub const ParamDecl = struct {
959 base: Node = Node {.id = .ParamDecl},
962 base: Node = Node{ .id = .ParamDecl },
960963 doc_comments: ?*DocComment,
961964 comptime_token: ?TokenIndex,
962965 noalias_token: ?TokenIndex,
......@@ -989,7 +992,7 @@ pub const Node = struct {
989992 };
990993
991994 pub const Block = struct {
992 base: Node = Node {.id = .Block},
995 base: Node = Node{ .id = .Block },
993996 label: ?TokenIndex,
994997 lbrace: TokenIndex,
995998 statements: StatementList,
......@@ -1020,7 +1023,7 @@ pub const Node = struct {
10201023 };
10211024
10221025 pub const Defer = struct {
1023 base: Node = Node {.id = .Defer},
1026 base: Node = Node{ .id = .Defer },
10241027 defer_token: TokenIndex,
10251028 expr: *Node,
10261029
......@@ -1043,7 +1046,7 @@ pub const Node = struct {
10431046 };
10441047
10451048 pub const Comptime = struct {
1046 base: Node = Node {.id = .Comptime},
1049 base: Node = Node{ .id = .Comptime },
10471050 doc_comments: ?*DocComment,
10481051 comptime_token: TokenIndex,
10491052 expr: *Node,
......@@ -1067,7 +1070,7 @@ pub const Node = struct {
10671070 };
10681071
10691072 pub const Payload = struct {
1070 base: Node = Node {.id = .Payload},
1073 base: Node = Node{ .id = .Payload },
10711074 lpipe: TokenIndex,
10721075 error_symbol: *Node,
10731076 rpipe: TokenIndex,
......@@ -1091,7 +1094,7 @@ pub const Node = struct {
10911094 };
10921095
10931096 pub const PointerPayload = struct {
1094 base: Node = Node {.id = .PointerPayload},
1097 base: Node = Node{ .id = .PointerPayload },
10951098 lpipe: TokenIndex,
10961099 ptr_token: ?TokenIndex,
10971100 value_symbol: *Node,
......@@ -1116,7 +1119,7 @@ pub const Node = struct {
11161119 };
11171120
11181121 pub const PointerIndexPayload = struct {
1119 base: Node = Node {.id = .PointerIndexPayload},
1122 base: Node = Node{ .id = .PointerIndexPayload },
11201123 lpipe: TokenIndex,
11211124 ptr_token: ?TokenIndex,
11221125 value_symbol: *Node,
......@@ -1147,7 +1150,7 @@ pub const Node = struct {
11471150 };
11481151
11491152 pub const Else = struct {
1150 base: Node = Node {.id = .Else},
1153 base: Node = Node{ .id = .Else },
11511154 else_token: TokenIndex,
11521155 payload: ?*Node,
11531156 body: *Node,
......@@ -1176,7 +1179,7 @@ pub const Node = struct {
11761179 };
11771180
11781181 pub const Switch = struct {
1179 base: Node = Node {.id = .Switch},
1182 base: Node = Node{ .id = .Switch },
11801183 switch_token: TokenIndex,
11811184 expr: *Node,
11821185
......@@ -1208,7 +1211,7 @@ pub const Node = struct {
12081211 };
12091212
12101213 pub const SwitchCase = struct {
1211 base: Node = Node {.id = .SwitchCase},
1214 base: Node = Node{ .id = .SwitchCase },
12121215 items: ItemList,
12131216 arrow_token: TokenIndex,
12141217 payload: ?*Node,
......@@ -1243,7 +1246,7 @@ pub const Node = struct {
12431246 };
12441247
12451248 pub const SwitchElse = struct {
1246 base: Node = Node {.id = .SwitchElse},
1249 base: Node = Node{ .id = .SwitchElse },
12471250 token: TokenIndex,
12481251
12491252 pub fn iterate(self: *SwitchElse, index: usize) ?*Node {
......@@ -1260,7 +1263,7 @@ pub const Node = struct {
12601263 };
12611264
12621265 pub const While = struct {
1263 base: Node = Node {.id = .While},
1266 base: Node = Node{ .id = .While },
12641267 label: ?TokenIndex,
12651268 inline_token: ?TokenIndex,
12661269 while_token: TokenIndex,
......@@ -1319,7 +1322,7 @@ pub const Node = struct {
13191322 };
13201323
13211324 pub const For = struct {
1322 base: Node = Node {.id = .For},
1325 base: Node = Node{ .id = .For },
13231326 label: ?TokenIndex,
13241327 inline_token: ?TokenIndex,
13251328 for_token: TokenIndex,
......@@ -1370,7 +1373,7 @@ pub const Node = struct {
13701373 };
13711374
13721375 pub const If = struct {
1373 base: Node = Node {.id = .If},
1376 base: Node = Node{ .id = .If },
13741377 if_token: TokenIndex,
13751378 condition: *Node,
13761379 payload: ?*Node,
......@@ -1413,7 +1416,7 @@ pub const Node = struct {
14131416 };
14141417
14151418 pub const InfixOp = struct {
1416 base: Node = Node {.id = .InfixOp},
1419 base: Node = Node{ .id = .InfixOp },
14171420 op_token: TokenIndex,
14181421 lhs: *Node,
14191422 op: Op,
......@@ -1646,7 +1649,7 @@ pub const Node = struct {
16461649 };
16471650
16481651 pub const FieldInitializer = struct {
1649 base: Node = Node {.id = .FieldInitializer},
1652 base: Node = Node{ .id = .FieldInitializer },
16501653 period_token: TokenIndex,
16511654 name_token: TokenIndex,
16521655 expr: *Node,
......@@ -1670,7 +1673,7 @@ pub const Node = struct {
16701673 };
16711674
16721675 pub const SuffixOp = struct {
1673 base: Node = Node {.id = .SuffixOp},
1676 base: Node = Node{ .id = .SuffixOp },
16741677 lhs: Lhs,
16751678 op: Op,
16761679 rtoken: TokenIndex,
......@@ -1771,7 +1774,7 @@ pub const Node = struct {
17711774 };
17721775
17731776 pub const GroupedExpression = struct {
1774 base: Node = Node {.id = .GroupedExpression},
1777 base: Node = Node{ .id = .GroupedExpression },
17751778 lparen: TokenIndex,
17761779 expr: *Node,
17771780 rparen: TokenIndex,
......@@ -1795,7 +1798,7 @@ pub const Node = struct {
17951798 };
17961799
17971800 pub const ControlFlowExpression = struct {
1798 base: Node = Node {.id = .ControlFlowExpression},
1801 base: Node = Node{ .id = .ControlFlowExpression },
17991802 ltoken: TokenIndex,
18001803 kind: Kind,
18011804 rhs: ?*Node,
......@@ -1861,7 +1864,7 @@ pub const Node = struct {
18611864 };
18621865
18631866 pub const Suspend = struct {
1864 base: Node = Node {.id = .Suspend},
1867 base: Node = Node{ .id = .Suspend },
18651868 suspend_token: TokenIndex,
18661869 body: ?*Node,
18671870
......@@ -1890,7 +1893,7 @@ pub const Node = struct {
18901893 };
18911894
18921895 pub const IntegerLiteral = struct {
1893 base: Node = Node {.id = .IntegerLiteral},
1896 base: Node = Node{ .id = .IntegerLiteral },
18941897 token: TokenIndex,
18951898
18961899 pub fn iterate(self: *IntegerLiteral, index: usize) ?*Node {
......@@ -1907,7 +1910,7 @@ pub const Node = struct {
19071910 };
19081911
19091912 pub const EnumLiteral = struct {
1910 base: Node = Node {.id = .EnumLiteral},
1913 base: Node = Node{ .id = .EnumLiteral },
19111914 dot: TokenIndex,
19121915 name: TokenIndex,
19131916
......@@ -1925,7 +1928,7 @@ pub const Node = struct {
19251928 };
19261929
19271930 pub const FloatLiteral = struct {
1928 base: Node = Node {.id = .FloatLiteral},
1931 base: Node = Node{ .id = .FloatLiteral },
19291932 token: TokenIndex,
19301933
19311934 pub fn iterate(self: *FloatLiteral, index: usize) ?*Node {
......@@ -1942,7 +1945,7 @@ pub const Node = struct {
19421945 };
19431946
19441947 pub const BuiltinCall = struct {
1945 base: Node = Node {.id = .BuiltinCall},
1948 base: Node = Node{ .id = .BuiltinCall },
19461949 builtin_token: TokenIndex,
19471950 params: ParamList,
19481951 rparen_token: TokenIndex,
......@@ -1968,7 +1971,7 @@ pub const Node = struct {
19681971 };
19691972
19701973 pub const StringLiteral = struct {
1971 base: Node = Node {.id = .StringLiteral},
1974 base: Node = Node{ .id = .StringLiteral },
19721975 token: TokenIndex,
19731976
19741977 pub fn iterate(self: *StringLiteral, index: usize) ?*Node {
......@@ -1985,7 +1988,7 @@ pub const Node = struct {
19851988 };
19861989
19871990 pub const MultilineStringLiteral = struct {
1988 base: Node = Node {.id = .MultilineStringLiteral},
1991 base: Node = Node{ .id = .MultilineStringLiteral },
19891992 lines: LineList,
19901993
19911994 pub const LineList = SegmentedList(TokenIndex, 4);
......@@ -2004,7 +2007,7 @@ pub const Node = struct {
20042007 };
20052008
20062009 pub const CharLiteral = struct {
2007 base: Node = Node {.id = .CharLiteral},
2010 base: Node = Node{ .id = .CharLiteral },
20082011 token: TokenIndex,
20092012
20102013 pub fn iterate(self: *CharLiteral, index: usize) ?*Node {
......@@ -2021,7 +2024,7 @@ pub const Node = struct {
20212024 };
20222025
20232026 pub const BoolLiteral = struct {
2024 base: Node = Node {.id = .BoolLiteral},
2027 base: Node = Node{ .id = .BoolLiteral },
20252028 token: TokenIndex,
20262029
20272030 pub fn iterate(self: *BoolLiteral, index: usize) ?*Node {
......@@ -2038,7 +2041,7 @@ pub const Node = struct {
20382041 };
20392042
20402043 pub const NullLiteral = struct {
2041 base: Node = Node {.id = .NullLiteral},
2044 base: Node = Node{ .id = .NullLiteral },
20422045 token: TokenIndex,
20432046
20442047 pub fn iterate(self: *NullLiteral, index: usize) ?*Node {
......@@ -2055,7 +2058,7 @@ pub const Node = struct {
20552058 };
20562059
20572060 pub const UndefinedLiteral = struct {
2058 base: Node = Node {.id = .UndefinedLiteral},
2061 base: Node = Node{ .id = .UndefinedLiteral },
20592062 token: TokenIndex,
20602063
20612064 pub fn iterate(self: *UndefinedLiteral, index: usize) ?*Node {
......@@ -2072,7 +2075,7 @@ pub const Node = struct {
20722075 };
20732076
20742077 pub const AsmOutput = struct {
2075 base: Node = Node {.id = .AsmOutput},
2078 base: Node = Node{ .id = .AsmOutput },
20762079 lbracket: TokenIndex,
20772080 symbolic_name: *Node,
20782081 constraint: *Node,
......@@ -2117,7 +2120,7 @@ pub const Node = struct {
21172120 };
21182121
21192122 pub const AsmInput = struct {
2120 base: Node = Node {.id = .AsmInput},
2123 base: Node = Node{ .id = .AsmInput },
21212124 lbracket: TokenIndex,
21222125 symbolic_name: *Node,
21232126 constraint: *Node,
......@@ -2149,7 +2152,7 @@ pub const Node = struct {
21492152 };
21502153
21512154 pub const Asm = struct {
2152 base: Node = Node {.id = .Asm},
2155 base: Node = Node{ .id = .Asm },
21532156 asm_token: TokenIndex,
21542157 volatile_token: ?TokenIndex,
21552158 template: *Node,
......@@ -2184,7 +2187,7 @@ pub const Node = struct {
21842187 };
21852188
21862189 pub const Unreachable = struct {
2187 base: Node = Node {.id = .Unreachable},
2190 base: Node = Node{ .id = .Unreachable },
21882191 token: TokenIndex,
21892192
21902193 pub fn iterate(self: *Unreachable, index: usize) ?*Node {
......@@ -2201,7 +2204,7 @@ pub const Node = struct {
22012204 };
22022205
22032206 pub const ErrorType = struct {
2204 base: Node = Node {.id = .ErrorType},
2207 base: Node = Node{ .id = .ErrorType },
22052208 token: TokenIndex,
22062209
22072210 pub fn iterate(self: *ErrorType, index: usize) ?*Node {
......@@ -2235,7 +2238,7 @@ pub const Node = struct {
22352238 };
22362239
22372240 pub const DocComment = struct {
2238 base: Node = Node {.id = .DocComment},
2241 base: Node = Node{ .id = .DocComment },
22392242 lines: LineList,
22402243
22412244 pub const LineList = SegmentedList(TokenIndex, 4);
......@@ -2254,7 +2257,7 @@ pub const Node = struct {
22542257 };
22552258
22562259 pub const TestDecl = struct {
2257 base: Node = Node {.id = .TestDecl},
2260 base: Node = Node{ .id = .TestDecl },
22582261 doc_comments: ?*DocComment,
22592262 test_token: TokenIndex,
22602263 name: *Node,
lib/std/zig/render.zig+1-1
......@@ -643,7 +643,7 @@ fn renderExpression(
643643 },
644644
645645 .ArrayAccess => |index_expr| {
646 const lbracket = tree.prevToken(index_expr.firstToken());
646 const lbracket = tree.nextToken(suffix_op.lhs.node.lastToken());
647647 const rbracket = tree.nextToken(index_expr.lastToken());
648648
649649 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
src-self-hosted/c_tokenizer.zig+214-73
......@@ -8,7 +8,7 @@ pub const TokenList = std.SegmentedList(CToken, 32);
88
99pub const CToken = struct {
1010 id: Id,
11 bytes: []const u8,
11 bytes: []const u8 = "",
1212 num_lit_suffix: NumLitSuffix = .None,
1313
1414 pub const Id = enum {
......@@ -17,20 +17,33 @@ pub const CToken = struct {
1717 NumLitInt,
1818 NumLitFloat,
1919 Identifier,
20 Plus,
2021 Minus,
2122 Slash,
2223 LParen,
2324 RParen,
2425 Eof,
2526 Dot,
26 Asterisk,
27 Bang,
28 Tilde,
29 Shl,
30 Lt,
27 Asterisk, // *
28 Ampersand, // &
29 And, // &&
30 Assign, // =
31 Or, // ||
32 Bang, // !
33 Tilde, // ~
34 Shl, // <<
35 Shr, // >>
36 Lt, // <
37 Lte, // <=
38 Gt, // >
39 Gte, // >=
40 Eq, // ==
41 Ne, // !=
42 Increment, // ++
43 Decrement, // --
3144 Comma,
3245 Fn,
33 Arrow,
46 Arrow, // ->
3447 LBrace,
3548 RBrace,
3649 Pipe,
......@@ -225,7 +238,14 @@ fn zigifyEscapeSequences(ctx: *Context, loc: ZigClangSourceLocation, name: []con
225238fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:0]const u8, i: *usize) !CToken {
226239 var state: enum {
227240 Start,
228 GotLt,
241 SawLt,
242 SawGt,
243 SawPlus,
244 SawMinus,
245 SawAmpersand,
246 SawPipe,
247 SawBang,
248 SawEq,
229249 CharLit,
230250 OpenComment,
231251 Comment,
......@@ -235,7 +255,7 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
235255 Identifier,
236256 Decimal,
237257 Octal,
238 GotZero,
258 SawZero,
239259 Hex,
240260 Bin,
241261 Float,
......@@ -246,7 +266,6 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
246266 NumLitIntSuffixL,
247267 NumLitIntSuffixLL,
248268 NumLitIntSuffixUL,
249 Minus,
250269 Done,
251270 } = .Start;
252271
......@@ -267,7 +286,7 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
267286 .Hex,
268287 .Bin,
269288 .Octal,
270 .GotZero,
289 .SawZero,
271290 .Float,
272291 .FloatExp,
273292 => {
......@@ -275,13 +294,19 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
275294 return result;
276295 },
277296 .Start,
278 .Minus,
297 .SawMinus,
279298 .Done,
280299 .NumLitIntSuffixU,
281300 .NumLitIntSuffixL,
282301 .NumLitIntSuffixUL,
283302 .NumLitIntSuffixLL,
284 .GotLt,
303 .SawLt,
304 .SawGt,
305 .SawPlus,
306 .SawAmpersand,
307 .SawPipe,
308 .SawBang,
309 .SawEq,
285310 => {
286311 return result;
287312 },
......@@ -333,7 +358,7 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
333358 begin_index = i.*;
334359 },
335360 '0' => {
336 state = .GotZero;
361 state = .SawZero;
337362 result.id = .NumLitInt;
338363 begin_index = i.*;
339364 },
......@@ -343,7 +368,11 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
343368 },
344369 '<' => {
345370 result.id = .Lt;
346 state = .GotLt;
371 state = .SawLt;
372 },
373 '>' => {
374 result.id = .Gt;
375 state = .SawGt;
347376 },
348377 '(' => {
349378 result.id = .LParen;
......@@ -357,18 +386,26 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
357386 result.id = .Asterisk;
358387 state = .Done;
359388 },
389 '+' => {
390 result.id = .Plus;
391 state = .SawPlus;
392 },
360393 '-' => {
361 state = .Minus;
362394 result.id = .Minus;
395 state = .SawMinus;
363396 },
364397 '!' => {
365398 result.id = .Bang;
366 state = .Done;
399 state = .SawBang;
367400 },
368401 '~' => {
369402 result.id = .Tilde;
370403 state = .Done;
371404 },
405 '=' => {
406 result.id = .Assign;
407 state = .SawEq;
408 },
372409 ',' => {
373410 result.id = .Comma;
374411 state = .Done;
......@@ -383,7 +420,11 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
383420 },
384421 '|' => {
385422 result.id = .Pipe;
386 state = .Done;
423 state = .SawPipe;
424 },
425 '&' => {
426 result.id = .Ampersand;
427 state = .SawAmpersand;
387428 },
388429 '?' => {
389430 result.id = .QuestionMark;
......@@ -400,26 +441,88 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
400441 }
401442 },
402443 .Done => return result,
403 .Minus => {
444 .SawMinus => {
404445 switch (c) {
405446 '>' => {
406447 result.id = .Arrow;
407448 state = .Done;
408449 },
409 else => {
410 return result;
450 '-' => {
451 result.id = .Decrement;
452 state = .Done;
411453 },
454 else => return result,
412455 }
413456 },
414 .GotLt => {
457 .SawPlus => {
458 switch (c) {
459 '+' => {
460 result.id = .Increment;
461 state = .Done;
462 },
463 else => return result,
464 }
465 },
466 .SawLt => {
415467 switch (c) {
416468 '<' => {
417469 result.id = .Shl;
418470 state = .Done;
419471 },
420 else => {
421 return result;
472 '=' => {
473 result.id = .Lte;
474 state = .Done;
475 },
476 else => return result,
477 }
478 },
479 .SawGt => {
480 switch (c) {
481 '>' => {
482 result.id = .Shr;
483 state = .Done;
484 },
485 '=' => {
486 result.id = .Gte;
487 state = .Done;
488 },
489 else => return result,
490 }
491 },
492 .SawPipe => {
493 switch (c) {
494 '|' => {
495 result.id = .Or;
496 state = .Done;
497 },
498 else => return result,
499 }
500 },
501 .SawAmpersand => {
502 switch (c) {
503 '&' => {
504 result.id = .And;
505 state = .Done;
506 },
507 else => return result,
508 }
509 },
510 .SawBang => {
511 switch (c) {
512 '=' => {
513 result.id = .Ne;
514 state = .Done;
422515 },
516 else => return result,
517 }
518 },
519 .SawEq => {
520 switch (c) {
521 '=' => {
522 result.id = .Eq;
523 state = .Done;
524 },
525 else => return result,
423526 }
424527 },
425528 .Float => {
......@@ -454,7 +557,7 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
454557 '0'...'9' => {
455558 state = .FloatExp;
456559 },
457 else => {
560 else => {
458561 try failDecl(ctx, loc, name, "macro tokenizing failed: expected a digit or '+' or '-'", .{});
459562 return error.TokenizingFailed;
460563 },
......@@ -514,7 +617,7 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
514617 },
515618 }
516619 },
517 .GotZero => {
620 .SawZero => {
518621 switch (c) {
519622 'x', 'X' => {
520623 state = .Hex;
......@@ -726,76 +829,114 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
726829 unreachable;
727830}
728831
832fn expectTokens(tl: *TokenList, src: [*:0]const u8, expected: []CToken) void {
833 // these can be undefined since they are only used for error reporting
834 tokenizeCMacro(undefined, undefined, undefined, tl, src) catch unreachable;
835 var it = tl.iterator(0);
836 for (expected) |t| {
837 var tok = it.next().?;
838 std.testing.expectEqual(t.id, tok.id);
839 if (t.bytes.len > 0) {
840 //std.debug.warn(" {} = {}\n", .{tok.bytes, t.bytes});
841 std.testing.expectEqualSlices(u8, tok.bytes, t.bytes);
842 }
843 if (t.num_lit_suffix != .None) {
844 std.testing.expectEqual(t.num_lit_suffix, tok.num_lit_suffix);
845 }
846 }
847 std.testing.expect(it.next() == null);
848 tl.shrink(0);
849}
850
729851test "tokenize macro" {
730852 var tl = TokenList.init(std.heap.page_allocator);
731853 defer tl.deinit();
732854
733 const src = "TEST(0\n";
734 try tokenizeCMacro(&tl, src);
735 var it = tl.iterator(0);
736 expect(it.next().?.id == .Identifier);
737 expect(it.next().?.id == .Fn);
738 expect(it.next().?.id == .LParen);
739 expect(std.mem.eql(u8, it.next().?.bytes, "0"));
740 expect(it.next().?.id == .Eof);
741 expect(it.next() == null);
742 tl.shrink(0);
855 expectTokens(&tl, "TEST(0\n", &[_]CToken{
856 .{ .id = .Identifier, .bytes = "TEST" },
857 .{ .id = .Fn },
858 .{ .id = .LParen },
859 .{ .id = .NumLitInt, .bytes = "0" },
860 .{ .id = .Eof },
861 });
743862
744 const src2 = "__FLT_MIN_10_EXP__ -37\n";
745 try tokenizeCMacro(&tl, src2);
746 it = tl.iterator(0);
747 expect(std.mem.eql(u8, it.next().?.bytes, "__FLT_MIN_10_EXP__"));
748 expect(it.next().?.id == .Minus);
749 expect(std.mem.eql(u8, it.next().?.bytes, "37"));
750 expect(it.next().?.id == .Eof);
751 expect(it.next() == null);
752 tl.shrink(0);
863 expectTokens(&tl, "__FLT_MIN_10_EXP__ -37\n", &[_]CToken{
864 .{ .id = .Identifier, .bytes = "__FLT_MIN_10_EXP__" },
865 .{ .id = .Minus },
866 .{ .id = .NumLitInt, .bytes = "37" },
867 .{ .id = .Eof },
868 });
753869
754 const src3 = "__llvm__ 1\n#define";
755 try tokenizeCMacro(&tl, src3);
756 it = tl.iterator(0);
757 expect(std.mem.eql(u8, it.next().?.bytes, "__llvm__"));
758 expect(std.mem.eql(u8, it.next().?.bytes, "1"));
759 expect(it.next().?.id == .Eof);
760 expect(it.next() == null);
761 tl.shrink(0);
870 expectTokens(&tl, "__llvm__ 1\n#define", &[_]CToken{
871 .{ .id = .Identifier, .bytes = "__llvm__" },
872 .{ .id = .NumLitInt, .bytes = "1" },
873 .{ .id = .Eof },
874 });
762875
763 const src4 = "TEST 2";
764 try tokenizeCMacro(&tl, src4);
765 it = tl.iterator(0);
766 expect(it.next().?.id == .Identifier);
767 expect(std.mem.eql(u8, it.next().?.bytes, "2"));
768 expect(it.next().?.id == .Eof);
769 expect(it.next() == null);
770 tl.shrink(0);
876 expectTokens(&tl, "TEST 2", &[_]CToken{
877 .{ .id = .Identifier, .bytes = "TEST" },
878 .{ .id = .NumLitInt, .bytes = "2" },
879 .{ .id = .Eof },
880 });
771881
772 const src5 = "FOO 0ull";
773 try tokenizeCMacro(&tl, src5);
774 it = tl.iterator(0);
775 expect(it.next().?.id == .Identifier);
776 expect(std.mem.eql(u8, it.next().?.bytes, "0"));
777 expect(it.next().?.id == .Eof);
778 expect(it.next() == null);
779 tl.shrink(0);
882 expectTokens(&tl, "FOO 0ull", &[_]CToken{
883 .{ .id = .Identifier, .bytes = "FOO" },
884 .{ .id = .NumLitInt, .bytes = "0", .num_lit_suffix = .LLU },
885 .{ .id = .Eof },
886 });
887}
888
889test "tokenize macro ops" {
890 var tl = TokenList.init(std.heap.page_allocator);
891 defer tl.deinit();
892
893 expectTokens(&tl, "ADD A + B", &[_]CToken{
894 .{ .id = .Identifier, .bytes = "ADD" },
895 .{ .id = .Identifier, .bytes = "A" },
896 .{ .id = .Plus },
897 .{ .id = .Identifier, .bytes = "B" },
898 .{ .id = .Eof },
899 });
900
901 expectTokens(&tl, "ADD (A) + B", &[_]CToken{
902 .{ .id = .Identifier, .bytes = "ADD" },
903 .{ .id = .LParen },
904 .{ .id = .Identifier, .bytes = "A" },
905 .{ .id = .RParen },
906 .{ .id = .Plus },
907 .{ .id = .Identifier, .bytes = "B" },
908 .{ .id = .Eof },
909 });
910
911 expectTokens(&tl, "ADD (A) + B", &[_]CToken{
912 .{ .id = .Identifier, .bytes = "ADD" },
913 .{ .id = .LParen },
914 .{ .id = .Identifier, .bytes = "A" },
915 .{ .id = .RParen },
916 .{ .id = .Plus },
917 .{ .id = .Identifier, .bytes = "B" },
918 .{ .id = .Eof },
919 });
780920}
781921
782922test "escape sequences" {
783923 var buf: [1024]u8 = undefined;
784924 var alloc = std.heap.FixedBufferAllocator.init(buf[0..]);
785925 const a = &alloc.allocator;
786 expect(std.mem.eql(u8, (try zigifyEscapeSequences(a, .{
926 // these can be undefined since they are only used for error reporting
927 expect(std.mem.eql(u8, (try zigifyEscapeSequences(undefined, undefined, undefined, a, .{
787928 .id = .StrLit,
788929 .bytes = "\\x0077",
789930 })).bytes, "\\x77"));
790 expect(std.mem.eql(u8, (try zigifyEscapeSequences(a, .{
931 expect(std.mem.eql(u8, (try zigifyEscapeSequences(undefined, undefined, undefined, a, .{
791932 .id = .StrLit,
792933 .bytes = "\\24500",
793934 })).bytes, "\\xa500"));
794 expect(std.mem.eql(u8, (try zigifyEscapeSequences(a, .{
935 expect(std.mem.eql(u8, (try zigifyEscapeSequences(undefined, undefined, undefined, a, .{
795936 .id = .StrLit,
796937 .bytes = "\\x0077 abc",
797938 })).bytes, "\\x77 abc"));
798 expect(std.mem.eql(u8, (try zigifyEscapeSequences(a, .{
939 expect(std.mem.eql(u8, (try zigifyEscapeSequences(undefined, undefined, undefined, a, .{
799940 .id = .StrLit,
800941 .bytes = "\\045abc",
801942 })).bytes, "\\x25abc"));
src-self-hosted/clang.zig+8-2
......@@ -43,6 +43,7 @@ pub const struct_ZigClangImplicitCastExpr = @OpaqueType();
4343pub const struct_ZigClangIncompleteArrayType = @OpaqueType();
4444pub const struct_ZigClangIntegerLiteral = @OpaqueType();
4545pub const struct_ZigClangMacroDefinitionRecord = @OpaqueType();
46pub const struct_ZigClangMacroExpansion = @OpaqueType();
4647pub const struct_ZigClangMacroQualifiedType = @OpaqueType();
4748pub const struct_ZigClangMemberExpr = @OpaqueType();
4849pub const struct_ZigClangNamedDecl = @OpaqueType();
......@@ -803,8 +804,8 @@ pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *cons
803804pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
804805pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
805806pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
806pub extern fn ZigClangExpr_getStmtClass(self: ?*const struct_ZigClangExpr) ZigClangStmtClass;
807pub extern fn ZigClangExpr_getType(self: ?*const struct_ZigClangExpr) struct_ZigClangQualType;
807pub extern fn ZigClangExpr_getStmtClass(self: *const struct_ZigClangExpr) ZigClangStmtClass;
808pub extern fn ZigClangExpr_getType(self: *const struct_ZigClangExpr) struct_ZigClangQualType;
808809pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
809810pub extern fn ZigClangInitListExpr_getInit(self: ?*const struct_ZigClangInitListExpr, i: c_uint) *const ZigClangExpr;
810811pub extern fn ZigClangInitListExpr_getArrayFiller(self: ?*const struct_ZigClangInitListExpr) *const ZigClangExpr;
......@@ -831,6 +832,8 @@ pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bo
831832pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
832833pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
833834pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
835pub extern fn ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(self: *const ZigClangFunctionDecl) bool;
836pub extern fn ZigClangFunctionDecl_isInlineSpecified(self: *const ZigClangFunctionDecl) bool;
834837
835838pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;
836839
......@@ -889,6 +892,7 @@ pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr;
889892pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType;
890893pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral;
891894pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord;
895pub const ZigClangMacroExpansion = struct_ZigClangMacroExpansion;
892896pub const ZigClangMacroQualifiedType = struct_ZigClangMacroQualifiedType;
893897pub const ZigClangMemberExpr = struct_ZigClangMemberExpr;
894898pub const ZigClangNamedDecl = struct_ZigClangNamedDecl;
......@@ -1058,6 +1062,8 @@ pub extern fn ZigClangMacroDefinitionRecord_getName_getNameStart(*const ZigClang
10581062pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getBegin(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation;
10591063pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getEnd(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation;
10601064
1065pub extern fn ZigClangMacroExpansion_getDefinition(*const ZigClangMacroExpansion) *const ZigClangMacroDefinitionRecord;
1066
10611067pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt;
10621068pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt;
10631069pub extern fn ZigClangIfStmt_getCond(*const ZigClangIfStmt) *const ZigClangStmt;
src-self-hosted/link.zig+5-5
......@@ -119,11 +119,11 @@ fn linkDiagCallbackErrorable(ctx: *Context, msg: []const u8) !void {
119119
120120fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType {
121121 return switch (ofmt) {
122 .unknown => c.ZigLLVM_UnknownObjectFormat,
123 .coff => c.ZigLLVM_COFF,
124 .elf => c.ZigLLVM_ELF,
125 .macho => c.ZigLLVM_MachO,
126 .wasm => c.ZigLLVM_Wasm,
122 .unknown => .ZigLLVM_UnknownObjectFormat,
123 .coff => .ZigLLVM_COFF,
124 .elf => .ZigLLVM_ELF,
125 .macho => .ZigLLVM_MachO,
126 .wasm => .ZigLLVM_Wasm,
127127 };
128128}
129129
src-self-hosted/llvm.zig+22-22
......@@ -226,24 +226,24 @@ pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
226226pub const ReturnStatusAction = VerifierFailureAction.LLVMReturnStatusAction;
227227pub const VerifierFailureAction = c.LLVMVerifierFailureAction;
228228
229pub const CodeGenLevelNone = c.LLVMCodeGenOptLevel.LLVMCodeGenLevelNone;
230pub const CodeGenLevelLess = c.LLVMCodeGenOptLevel.LLVMCodeGenLevelLess;
231pub const CodeGenLevelDefault = c.LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault;
232pub const CodeGenLevelAggressive = c.LLVMCodeGenOptLevel.LLVMCodeGenLevelAggressive;
229pub const CodeGenLevelNone = CodeGenOptLevel.LLVMCodeGenLevelNone;
230pub const CodeGenLevelLess = CodeGenOptLevel.LLVMCodeGenLevelLess;
231pub const CodeGenLevelDefault = CodeGenOptLevel.LLVMCodeGenLevelDefault;
232pub const CodeGenLevelAggressive = CodeGenOptLevel.LLVMCodeGenLevelAggressive;
233233pub const CodeGenOptLevel = c.LLVMCodeGenOptLevel;
234234
235pub const RelocDefault = c.LLVMRelocMode.LLVMRelocDefault;
236pub const RelocStatic = c.LLVMRelocMode.LLVMRelocStatic;
237pub const RelocPIC = c.LLVMRelocMode.LLVMRelocPIC;
238pub const RelocDynamicNoPic = c.LLVMRelocMode.LLVMRelocDynamicNoPic;
235pub const RelocDefault = RelocMode.LLVMRelocDefault;
236pub const RelocStatic = RelocMode.LLVMRelocStatic;
237pub const RelocPIC = RelocMode.LLVMRelocPIC;
238pub const RelocDynamicNoPic = RelocMode.LLVMRelocDynamicNoPic;
239239pub const RelocMode = c.LLVMRelocMode;
240240
241pub const CodeModelDefault = c.LLVMCodeModel.LLVMCodeModelDefault;
242pub const CodeModelJITDefault = c.LLVMCodeModel.LLVMCodeModelJITDefault;
243pub const CodeModelSmall = c.LLVMCodeModel.LLVMCodeModelSmall;
244pub const CodeModelKernel = c.LLVMCodeModel.LLVMCodeModelKernel;
245pub const CodeModelMedium = c.LLVMCodeModel.LLVMCodeModelMedium;
246pub const CodeModelLarge = c.LLVMCodeModel.LLVMCodeModelLarge;
241pub const CodeModelDefault = CodeModel.LLVMCodeModelDefault;
242pub const CodeModelJITDefault = CodeModel.LLVMCodeModelJITDefault;
243pub const CodeModelSmall = CodeModel.LLVMCodeModelSmall;
244pub const CodeModelKernel = CodeModel.LLVMCodeModelKernel;
245pub const CodeModelMedium = CodeModel.LLVMCodeModelMedium;
246pub const CodeModelLarge = CodeModel.LLVMCodeModelLarge;
247247pub const CodeModel = c.LLVMCodeModel;
248248
249249pub const EmitAssembly = EmitOutputType.ZigLLVM_EmitAssembly;
......@@ -251,13 +251,13 @@ pub const EmitBinary = EmitOutputType.ZigLLVM_EmitBinary;
251251pub const EmitLLVMIr = EmitOutputType.ZigLLVM_EmitLLVMIr;
252252pub const EmitOutputType = c.ZigLLVM_EmitOutputType;
253253
254pub const CCallConv = c.LLVMCCallConv;
255pub const FastCallConv = c.LLVMFastCallConv;
256pub const ColdCallConv = c.LLVMColdCallConv;
257pub const WebKitJSCallConv = c.LLVMWebKitJSCallConv;
258pub const AnyRegCallConv = c.LLVMAnyRegCallConv;
259pub const X86StdcallCallConv = c.LLVMX86StdcallCallConv;
260pub const X86FastcallCallConv = c.LLVMX86FastcallCallConv;
254pub const CCallConv = CallConv.LLVMCCallConv;
255pub const FastCallConv = CallConv.LLVMFastCallConv;
256pub const ColdCallConv = CallConv.LLVMColdCallConv;
257pub const WebKitJSCallConv = CallConv.LLVMWebKitJSCallConv;
258pub const AnyRegCallConv = CallConv.LLVMAnyRegCallConv;
259pub const X86StdcallCallConv = CallConv.LLVMX86StdcallCallConv;
260pub const X86FastcallCallConv = CallConv.LLVMX86FastcallCallConv;
261261pub const CallConv = c.LLVMCallConv;
262262
263263pub const CallAttr = extern enum {
......@@ -288,6 +288,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
288288) bool;
289289
290290pub const BuildCall = ZigLLVMBuildCall;
291extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: CallAttr, Name: [*:0]const u8) ?*Value;
291extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: CallConv, fn_inline: CallAttr, Name: [*:0]const u8) ?*Value;
292292
293293pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/stage1.zig+1-1
......@@ -95,7 +95,7 @@ export fn stage2_translate_c(
9595 args_end: [*]?[*]const u8,
9696 resources_path: [*:0]const u8,
9797) Error {
98 var errors: []translate_c.ClangErrMsg = undefined;
98 var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
9999 out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
100100 error.SemanticAnalyzeFail => {
101101 out_errors_ptr.* = errors.ptr;
src-self-hosted/translate_c.zig+521-170
......@@ -9,6 +9,7 @@ usingnamespace @import("clang.zig");
99const ctok = @import("c_tokenizer.zig");
1010const CToken = ctok.CToken;
1111const mem = std.mem;
12const math = std.math;
1213
1314const CallingConvention = std.builtin.TypeInfo.CallingConvention;
1415
......@@ -64,6 +65,7 @@ const Scope = struct {
6465 block_node: *ast.Node.Block,
6566 variables: AliasList,
6667 label: ?[]const u8,
68 mangle_count: u32 = 0,
6769
6870 /// Don't forget to set rbrace token and block_node later
6971 fn init(c: *Context, parent: *Scope, label: ?[]const u8) !*Block {
......@@ -80,7 +82,19 @@ const Scope = struct {
8082 return block;
8183 }
8284
83 fn getAlias(scope: *Block, name: []const u8) ?[]const u8 {
85 /// Given the desired name, return a name that does not shadow anything from outer scopes.
86 /// Inserts the returned name into the scope.
87 fn makeMangledName(scope: *Block, c: *Context, name: []const u8) ![]const u8 {
88 var proposed_name = name;
89 while (scope.contains(proposed_name)) {
90 scope.mangle_count += 1;
91 proposed_name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, scope.mangle_count });
92 }
93 try scope.variables.push(.{ .name = name, .alias = proposed_name });
94 return proposed_name;
95 }
96
97 fn getAlias(scope: *Block, name: []const u8) []const u8 {
8498 var it = scope.variables.iterator(0);
8599 while (it.next()) |p| {
86100 if (mem.eql(u8, p.name, name))
......@@ -89,12 +103,18 @@ const Scope = struct {
89103 return scope.base.parent.?.getAlias(name);
90104 }
91105
92 fn contains(scope: *Block, name: []const u8) bool {
106 fn localContains(scope: *Block, name: []const u8) bool {
93107 var it = scope.variables.iterator(0);
94108 while (it.next()) |p| {
95109 if (mem.eql(u8, p.name, name))
96110 return true;
97111 }
112 return false;
113 }
114
115 fn contains(scope: *Block, name: []const u8) bool {
116 if (scope.localContains(name))
117 return true;
98118 return scope.base.parent.?.contains(name);
99119 }
100120 };
......@@ -103,6 +123,7 @@ const Scope = struct {
103123 base: Scope,
104124 sym_table: SymbolTable,
105125 macro_table: SymbolTable,
126 context: *Context,
106127
107128 fn init(c: *Context) Root {
108129 return .{
......@@ -112,11 +133,21 @@ const Scope = struct {
112133 },
113134 .sym_table = SymbolTable.init(c.a()),
114135 .macro_table = SymbolTable.init(c.a()),
136 .context = c,
115137 };
116138 }
117139
140 /// Check if the global scope contains this name, without looking into the "future", e.g.
141 /// ignore the preprocessed decl and macro names.
142 fn containsNow(scope: *Root, name: []const u8) bool {
143 return isZigPrimitiveType(name) or
144 scope.sym_table.contains(name) or
145 scope.macro_table.contains(name);
146 }
147
148 /// Check if the global scope contains the name, includes all decls that haven't been translated yet.
118149 fn contains(scope: *Root, name: []const u8) bool {
119 return scope.sym_table.contains(name) or scope.macro_table.contains(name);
150 return scope.containsNow(name) or scope.context.global_names.contains(name);
120151 }
121152 };
122153
......@@ -135,16 +166,9 @@ const Scope = struct {
135166 }
136167 }
137168
138 fn createAlias(scope: *Scope, c: *Context, name: []const u8) !?[]const u8 {
139 if (isZigPrimitiveType(name) or scope.contains(name)) {
140 return try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() });
141 }
142 return null;
143 }
144
145 fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 {
169 fn getAlias(scope: *Scope, name: []const u8) []const u8 {
146170 return switch (scope.id) {
147 .Root => null,
171 .Root => return name,
148172 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
149173 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
150174 };
......@@ -191,9 +215,15 @@ pub const Context = struct {
191215 alias_list: AliasList,
192216 global_scope: *Scope.Root,
193217 clang_context: *ZigClangASTContext,
194 mangle_count: u64 = 0,
218 mangle_count: u32 = 0,
219
220 /// This one is different than the root scope's name table. This contains
221 /// a list of names that we found by visiting all the top level decls without
222 /// translating them. The other maps are updated as we translate; this one is updated
223 /// up front in a pre-processing step.
224 global_names: std.StringHashMap(void),
195225
196 fn getMangle(c: *Context) u64 {
226 fn getMangle(c: *Context) u32 {
197227 c.mangle_count += 1;
198228 return c.mangle_count;
199229 }
......@@ -249,6 +279,7 @@ pub fn translate(
249279 .arena_allocator = tree_arena,
250280 .tokens = undefined, // can't reference the allocator yet
251281 .errors = undefined, // can't reference the allocator yet
282 .generated = true,
252283 };
253284 break :blk tree;
254285 };
......@@ -276,9 +307,12 @@ pub fn translate(
276307 .alias_list = AliasList.init(arena),
277308 .global_scope = try arena.create(Scope.Root),
278309 .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
310 .global_names = std.StringHashMap(void).init(arena),
279311 };
280312 context.global_scope.* = Scope.Root.init(&context);
281313
314 try prepopulateGlobalNameTable(ast_unit, &context);
315
282316 if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) {
283317 return context.err;
284318 }
......@@ -306,6 +340,38 @@ pub fn translate(
306340 return tree;
307341}
308342
343fn prepopulateGlobalNameTable(ast_unit: *ZigClangASTUnit, c: *Context) !void {
344 if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, declVisitorNamesOnlyC)) {
345 return c.err;
346 }
347
348 // TODO if we see #undef, delete it from the table
349 var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(ast_unit);
350 const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(ast_unit);
351
352 while (it.I != it_end.I) : (it.I += 1) {
353 const entity = ZigClangPreprocessingRecord_iterator_deref(it);
354 switch (ZigClangPreprocessedEntity_getKind(entity)) {
355 .MacroDefinitionKind => {
356 const macro = @ptrCast(*ZigClangMacroDefinitionRecord, entity);
357 const raw_name = ZigClangMacroDefinitionRecord_getName_getNameStart(macro);
358 const name = try c.str(raw_name);
359 _ = try c.global_names.put(name, {});
360 },
361 else => {},
362 }
363 }
364}
365
366extern fn declVisitorNamesOnlyC(context: ?*c_void, decl: *const ZigClangDecl) bool {
367 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
368 declVisitorNamesOnly(c, decl) catch |err| {
369 c.err = err;
370 return false;
371 };
372 return true;
373}
374
309375extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool {
310376 const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
311377 declVisitor(c, decl) catch |err| {
......@@ -315,6 +381,11 @@ extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool {
315381 return true;
316382}
317383
384fn declVisitorNamesOnly(c: *Context, decl: *const ZigClangDecl) Error!void {
385 const decl_name = try c.str(ZigClangDecl_getName_bytes_begin(decl));
386 _ = try c.global_names.put(decl_name, {});
387}
388
318389fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
319390 switch (ZigClangDecl_getKind(decl)) {
320391 .Function => {
......@@ -352,7 +423,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
352423 .has_body = has_body,
353424 .storage_class = storage_class,
354425 .is_export = switch (storage_class) {
355 .None => has_body,
426 .None => has_body and !ZigClangFunctionDecl_isInlineSpecified(fn_decl),
356427 .Extern, .Static => false,
357428 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
358429 .Auto => unreachable, // Not legal on functions
......@@ -409,13 +480,14 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
409480 const param_name = tokenSlice(c, param.name_token orelse
410481 return failDecl(c, fn_decl_loc, fn_name, "function {} parameter has no name", .{fn_name}));
411482
412 const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
413 try block_scope.variables.push(.{ .name = param_name, .alias = a });
414 break :blk a;
415 } else param_name;
416 const arg_name = try std.fmt.allocPrint(c.a(), "_arg_{}", .{checked_param_name});
483 const mangled_param_name = try block_scope.makeMangledName(c, param_name);
484
485 const arg_name = blk: {
486 const bare_arg_name = try std.fmt.allocPrint(c.a(), "arg_{}", .{mangled_param_name});
487 break :blk try block_scope.makeMangledName(c, bare_arg_name);
488 };
417489
418 const node = try transCreateNodeVarDecl(c, false, false, checked_param_name);
490 const node = try transCreateNodeVarDecl(c, false, false, mangled_param_name);
419491 node.eq_token = try appendToken(c, .Equal, "=");
420492 node.init_node = try transCreateNodeIdentifier(c, arg_name);
421493 node.semicolon_token = try appendToken(c, .Semicolon, ";");
......@@ -483,10 +555,13 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
483555 var eq_tok: ast.TokenIndex = undefined;
484556 var init_node: ?*ast.Node = null;
485557
558 // If the initialization expression is not present, initialize with undefined.
559 // If it is an integer literal, we can skip the @as since it will be redundant
560 // with the variable type.
486561 if (ZigClangVarDecl_hasInit(var_decl)) {
487562 eq_tok = try appendToken(c, .Equal, "=");
488563 init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
489 transExpr(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {
564 transExprCoercing(rp, &c.global_scope.base, expr, .used, .r_value) catch |err| switch (err) {
490565 error.UnsupportedTranslation,
491566 error.UnsupportedType,
492567 => {
......@@ -532,49 +607,53 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl) Error
532607
533608 const typedef_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_decl)));
534609
535 if (mem.eql(u8, typedef_name, "uint8_t"))
610 // TODO https://github.com/ziglang/zig/issues/3756
611 // TODO https://github.com/ziglang/zig/issues/1802
612 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "_{}", .{typedef_name}) else typedef_name;
613
614 if (mem.eql(u8, checked_name, "uint8_t"))
536615 return transTypeDefAsBuiltin(c, typedef_decl, "u8")
537 else if (mem.eql(u8, typedef_name, "int8_t"))
616 else if (mem.eql(u8, checked_name, "int8_t"))
538617 return transTypeDefAsBuiltin(c, typedef_decl, "i8")
539 else if (mem.eql(u8, typedef_name, "uint16_t"))
618 else if (mem.eql(u8, checked_name, "uint16_t"))
540619 return transTypeDefAsBuiltin(c, typedef_decl, "u16")
541 else if (mem.eql(u8, typedef_name, "int16_t"))
620 else if (mem.eql(u8, checked_name, "int16_t"))
542621 return transTypeDefAsBuiltin(c, typedef_decl, "i16")
543 else if (mem.eql(u8, typedef_name, "uint32_t"))
622 else if (mem.eql(u8, checked_name, "uint32_t"))
544623 return transTypeDefAsBuiltin(c, typedef_decl, "u32")
545 else if (mem.eql(u8, typedef_name, "int32_t"))
624 else if (mem.eql(u8, checked_name, "int32_t"))
546625 return transTypeDefAsBuiltin(c, typedef_decl, "i32")
547 else if (mem.eql(u8, typedef_name, "uint64_t"))
626 else if (mem.eql(u8, checked_name, "uint64_t"))
548627 return transTypeDefAsBuiltin(c, typedef_decl, "u64")
549 else if (mem.eql(u8, typedef_name, "int64_t"))
628 else if (mem.eql(u8, checked_name, "int64_t"))
550629 return transTypeDefAsBuiltin(c, typedef_decl, "i64")
551 else if (mem.eql(u8, typedef_name, "intptr_t"))
630 else if (mem.eql(u8, checked_name, "intptr_t"))
552631 return transTypeDefAsBuiltin(c, typedef_decl, "isize")
553 else if (mem.eql(u8, typedef_name, "uintptr_t"))
632 else if (mem.eql(u8, checked_name, "uintptr_t"))
554633 return transTypeDefAsBuiltin(c, typedef_decl, "usize")
555 else if (mem.eql(u8, typedef_name, "ssize_t"))
634 else if (mem.eql(u8, checked_name, "ssize_t"))
556635 return transTypeDefAsBuiltin(c, typedef_decl, "isize")
557 else if (mem.eql(u8, typedef_name, "size_t"))
636 else if (mem.eql(u8, checked_name, "size_t"))
558637 return transTypeDefAsBuiltin(c, typedef_decl, "usize");
559638
560 _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), typedef_name);
639 _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), checked_name);
561640 const visib_tok = try appendToken(c, .Keyword_pub, "pub");
562641 const const_tok = try appendToken(c, .Keyword_const, "const");
563 const node = try transCreateNodeVarDecl(c, true, true, typedef_name);
642 const node = try transCreateNodeVarDecl(c, true, true, checked_name);
564643 node.eq_token = try appendToken(c, .Equal, "=");
565644
566645 const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
567646 const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl);
568647 node.init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) {
569648 error.UnsupportedType => {
570 try failDecl(c, typedef_loc, typedef_name, "unable to resolve typedef child type", .{});
649 try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{});
571650 return null;
572651 },
573652 error.OutOfMemory => |e| return e,
574653 };
575654 node.semicolon_token = try appendToken(c, .Semicolon, ";");
576 try addTopLevelDecl(c, typedef_name, &node.base);
577 return transCreateNodeIdentifier(c, typedef_name);
655 try addTopLevelDecl(c, checked_name, &node.base);
656 return transCreateNodeIdentifier(c, checked_name);
578657}
579658
580659fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node {
......@@ -838,19 +917,19 @@ fn transStmt(
838917 .DeclStmtClass => return transDeclStmt(rp, scope, @ptrCast(*const ZigClangDeclStmt, stmt)),
839918 .DeclRefExprClass => return transDeclRefExpr(rp, scope, @ptrCast(*const ZigClangDeclRefExpr, stmt), lrvalue),
840919 .ImplicitCastExprClass => return transImplicitCastExpr(rp, scope, @ptrCast(*const ZigClangImplicitCastExpr, stmt), result_used),
841 .IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const ZigClangIntegerLiteral, stmt), result_used),
920 .IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const ZigClangIntegerLiteral, stmt), result_used, .with_as),
842921 .ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)),
843922 .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
844923 .ParenExprClass => {
845 const expr = try transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue);
846 if (expr.id == .GroupedExpression) return expr;
924 const expr = try transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), .used, lrvalue);
925 if (expr.id == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr);
847926 const node = try rp.c.a().create(ast.Node.GroupedExpression);
848927 node.* = .{
849928 .lparen = try appendToken(rp.c, .LParen, "("),
850929 .expr = expr,
851930 .rparen = try appendToken(rp.c, .RParen, ")"),
852931 };
853 return &node.base;
932 return maybeSuppressResult(rp, scope, result_used, &node.base);
854933 },
855934 .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used),
856935 .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
......@@ -872,7 +951,7 @@ fn transStmt(
872951 .DefaultStmtClass => return transDefault(rp, scope, @ptrCast(*const ZigClangDefaultStmt, stmt)),
873952 .ConstantExprClass => return transConstantExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used),
874953 .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
875 .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used),
954 .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used, .with_as),
876955 .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used),
877956 .MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const ZigClangMemberExpr, stmt), result_used),
878957 .ArraySubscriptExprClass => return transArrayAccess(rp, scope, @ptrCast(*const ZigClangArraySubscriptExpr, stmt), result_used),
......@@ -1132,11 +1211,8 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt)
11321211 const name = try c.str(ZigClangDecl_getName_bytes_begin(
11331212 @ptrCast(*const ZigClangDecl, var_decl),
11341213 ));
1135 const checked_name = if (try scope.createAlias(c, name)) |a| blk: {
1136 try block_scope.variables.push(.{ .name = name, .alias = a });
1137 break :blk a;
1138 } else name;
1139 const node = try transCreateNodeVarDecl(c, false, ZigClangQualType_isConstQualified(qual_type), checked_name);
1214 const mangled_name = try block_scope.makeMangledName(c, name);
1215 const node = try transCreateNodeVarDecl(c, false, ZigClangQualType_isConstQualified(qual_type), mangled_name);
11401216
11411217 _ = try appendToken(c, .Colon, ":");
11421218 const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt));
......@@ -1144,7 +1220,7 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt)
11441220
11451221 node.eq_token = try appendToken(c, .Equal, "=");
11461222 var init_node = if (ZigClangVarDecl_getInit(var_decl)) |expr|
1147 try transExpr(rp, scope, expr, .used, .r_value)
1223 try transExprCoercing(rp, scope, expr, .used, .r_value)
11481224 else
11491225 try transCreateNodeUndefinedLiteral(c);
11501226 if (isBoolRes(init_node)) {
......@@ -1177,8 +1253,8 @@ fn transDeclRefExpr(
11771253) TransError!*ast.Node {
11781254 const value_decl = ZigClangDeclRefExpr_getDecl(expr);
11791255 const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl)));
1180 const checked_name = if (scope.getAlias(name)) |a| a else name;
1181 return transCreateNodeIdentifier(rp.c, checked_name);
1256 const mangled_name = scope.getAlias(name);
1257 return transCreateNodeIdentifier(rp.c, mangled_name);
11821258}
11831259
11841260fn transImplicitCastExpr(
......@@ -1193,7 +1269,7 @@ fn transImplicitCastExpr(
11931269 const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr));
11941270 const src_type = getExprQualType(c, sub_expr);
11951271 switch (ZigClangImplicitCastExpr_getCastKind(expr)) {
1196 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast => {
1272 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {
11971273 return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node);
11981274 },
11991275 .LValueToRValue, .NoOp, .FunctionToPointerDecay, .ArrayToPointerDecay => {
......@@ -1220,29 +1296,6 @@ fn transImplicitCastExpr(
12201296 const rhs_node = try transCreateNodeInt(rp.c, 0);
12211297 return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, result_used, false);
12221298 },
1223 .PointerToIntegral => {
1224 // @intCast(dest_type, @ptrToInt(val))
1225 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
1226 try cast_node.params.push(try transQualType(rp, dest_type, ZigClangImplicitCastExpr_getBeginLoc(expr)));
1227 _ = try appendToken(rp.c, .Comma, ",");
1228
1229 const ptr_to_int = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
1230 try ptr_to_int.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value));
1231 ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")");
1232 try cast_node.params.push(&ptr_to_int.base);
1233 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1234 return maybeSuppressResult(rp, scope, result_used, &cast_node.base);
1235 },
1236 .IntegralToPointer => {
1237 // @intToPtr(dest_type, val)
1238 const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
1239 try int_to_ptr.params.push(try transQualType(rp, dest_type, ZigClangImplicitCastExpr_getBeginLoc(expr)));
1240 _ = try appendToken(rp.c, .Comma, ",");
1241
1242 try int_to_ptr.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value));
1243 int_to_ptr.rparen_token = try appendToken(rp.c, .RParen, ")");
1244 return maybeSuppressResult(rp, scope, result_used, &int_to_ptr.base);
1245 },
12461299 else => |kind| return revertAndWarn(
12471300 rp,
12481301 error.UnsupportedTranslation,
......@@ -1398,19 +1451,50 @@ fn finishBoolExpr(
13981451 return revertAndWarn(rp, error.UnsupportedType, loc, "unsupported bool expression type", .{});
13991452}
14001453
1454const SuppressCast = enum {
1455 with_as,
1456 no_as,
1457};
14011458fn transIntegerLiteral(
14021459 rp: RestorePoint,
14031460 scope: *Scope,
14041461 expr: *const ZigClangIntegerLiteral,
14051462 result_used: ResultUsed,
1463 suppress_as: SuppressCast,
14061464) TransError!*ast.Node {
14071465 var eval_result: ZigClangExprEvalResult = undefined;
14081466 if (!ZigClangIntegerLiteral_EvaluateAsInt(expr, &eval_result, rp.c.clang_context)) {
14091467 const loc = ZigClangIntegerLiteral_getBeginLoc(expr);
14101468 return revertAndWarn(rp, error.UnsupportedTranslation, loc, "invalid integer literal", .{});
14111469 }
1412 const node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val));
1413 return maybeSuppressResult(rp, scope, result_used, node);
1470
1471 if (suppress_as == .no_as) {
1472 const int_lit_node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val));
1473 return maybeSuppressResult(rp, scope, result_used, int_lit_node);
1474 }
1475
1476 // Integer literals in C have types, and this can matter for several reasons.
1477 // For example, this is valid C:
1478 // unsigned char y = 256;
1479 // How this gets evaluated is the 256 is an integer, which gets truncated to signed char, then bit-casted
1480 // to unsigned char, resulting in 0. In order for this to work, we have to emit this zig code:
1481 // var y = @bitCast(u8, @truncate(i8, @as(c_int, 256)));
1482 // Ideally in translate-c we could flatten this out to simply:
1483 // var y: u8 = 0;
1484 // But the first step is to be correct, and the next step is to make the output more elegant.
1485
1486 // @as(T, x)
1487 const expr_base = @ptrCast(*const ZigClangExpr, expr);
1488 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
1489 const ty_node = try transQualType(rp, ZigClangExpr_getType(expr_base), ZigClangExpr_getBeginLoc(expr_base));
1490 try as_node.params.push(ty_node);
1491 _ = try appendToken(rp.c, .Comma, ",");
1492
1493 const int_lit_node = try transCreateNodeAPInt(rp.c, ZigClangAPValue_getInt(&eval_result.Val));
1494 try as_node.params.push(int_lit_node);
1495
1496 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1497 return maybeSuppressResult(rp, scope, result_used, &as_node.base);
14141498}
14151499
14161500fn transReturnStmt(
......@@ -1420,7 +1504,7 @@ fn transReturnStmt(
14201504) TransError!*ast.Node {
14211505 const node = try transCreateNodeReturnExpr(rp.c);
14221506 if (ZigClangReturnStmt_getRetValue(expr)) |val_expr| {
1423 node.rhs = try transExpr(rp, scope, val_expr, .used, .r_value);
1507 node.rhs = try transExprCoercing(rp, scope, val_expr, .used, .r_value);
14241508 }
14251509 _ = try appendToken(rp.c, .Semicolon, ";");
14261510 return &node.base;
......@@ -1508,8 +1592,48 @@ fn transCCast(
15081592 if (ZigClangQualType_eq(dst_type, src_type)) return expr;
15091593 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
15101594 return transCPtrCast(rp, loc, dst_type, src_type, expr);
1511 if (cIsUnsignedInteger(dst_type) and qualTypeIsPtr(src_type)) {
1512 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
1595 if (cIsInteger(dst_type) and cIsInteger(src_type)) {
1596 // 1. Extend or truncate without changing signed-ness.
1597 // 2. Bit-cast to correct signed-ness
1598
1599 // @bitCast(dest_type, intermediate_value)
1600 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@bitCast");
1601 try cast_node.params.push(try transQualType(rp, dst_type, loc));
1602 _ = try appendToken(rp.c, .Comma, ",");
1603
1604 switch (cIntTypeCmp(dst_type, src_type)) {
1605 .lt => {
1606 // @truncate(SameSignSmallerInt, src_type)
1607 const trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@truncate");
1608 const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, cIsSignedInteger(src_type));
1609 try trunc_node.params.push(ty_node);
1610 _ = try appendToken(rp.c, .Comma, ",");
1611 try trunc_node.params.push(expr);
1612 trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1613
1614 try cast_node.params.push(&trunc_node.base);
1615 },
1616 .gt => {
1617 // @as(SameSignBiggerInt, src_type)
1618 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
1619 const ty_node = try transQualTypeIntWidthOf(rp.c, dst_type, cIsSignedInteger(src_type));
1620 try as_node.params.push(ty_node);
1621 _ = try appendToken(rp.c, .Comma, ",");
1622 try as_node.params.push(expr);
1623 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1624
1625 try cast_node.params.push(&as_node.base);
1626 },
1627 .eq => {
1628 try cast_node.params.push(expr);
1629 },
1630 }
1631 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1632 return &cast_node.base;
1633 }
1634 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
1635 // @intCast(dest_type, @ptrToInt(val))
1636 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
15131637 try cast_node.params.push(try transQualType(rp, dst_type, loc));
15141638 _ = try appendToken(rp.c, .Comma, ",");
15151639 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
......@@ -1519,7 +1643,8 @@ fn transCCast(
15191643 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
15201644 return &cast_node.base;
15211645 }
1522 if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) {
1646 if (cIsInteger(src_type) and qualTypeIsPtr(dst_type)) {
1647 // @intToPtr(dest_type, val)
15231648 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
15241649 try builtin_node.params.push(try transQualType(rp, dst_type, loc));
15251650 _ = try appendToken(rp.c, .Comma, ",");
......@@ -1575,9 +1700,6 @@ fn transCCast(
15751700 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
15761701 return &builtin_node.base;
15771702 }
1578 // TODO: maybe widen to increase size
1579 // TODO: maybe bitcast to change sign
1580 // TODO: maybe truncate to reduce size
15811703 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
15821704 try cast_node.params.push(try transQualType(rp, dst_type, loc));
15831705 _ = try appendToken(rp.c, .Comma, ",");
......@@ -1596,6 +1718,33 @@ fn transExpr(
15961718 return transStmt(rp, scope, @ptrCast(*const ZigClangStmt, expr), used, lrvalue);
15971719}
15981720
1721/// Same as `transExpr` but with the knowledge that the operand will be type coerced, and therefore
1722/// an `@as` would be redundant. This is used to prevent redundant `@as` in integer literals.
1723fn transExprCoercing(
1724 rp: RestorePoint,
1725 scope: *Scope,
1726 expr: *const ZigClangExpr,
1727 used: ResultUsed,
1728 lrvalue: LRValue,
1729) TransError!*ast.Node {
1730 switch (ZigClangStmt_getStmtClass(@ptrCast(*const ZigClangStmt, expr))) {
1731 .IntegerLiteralClass => {
1732 return transIntegerLiteral(rp, scope, @ptrCast(*const ZigClangIntegerLiteral, expr), .used, .no_as);
1733 },
1734 .CharacterLiteralClass => {
1735 return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, expr), .used, .no_as);
1736 },
1737 .UnaryOperatorClass => {
1738 const un_expr = @ptrCast(*const ZigClangUnaryOperator, expr);
1739 if (ZigClangUnaryOperator_getOpcode(un_expr) == .Extension) {
1740 return transExprCoercing(rp, scope, ZigClangUnaryOperator_getSubExpr(un_expr), used, lrvalue);
1741 }
1742 },
1743 else => {},
1744 }
1745 return transExpr(rp, scope, expr, .used, .r_value);
1746}
1747
15991748fn transInitListExpr(
16001749 rp: RestorePoint,
16011750 scope: *Scope,
......@@ -1621,7 +1770,7 @@ fn transInitListExpr(
16211770 const init_count = ZigClangInitListExpr_getNumInits(expr);
16221771 const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, qual_type);
16231772 const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
1624 const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize));
1773 const all_count = ZigClangAPInt_getLimitedValue(size_ap_int, math.maxInt(usize));
16251774 const leftover_count = all_count - init_count;
16261775
16271776 var init_node: *ast.Node.SuffixOp = undefined;
......@@ -1793,7 +1942,10 @@ fn transDoWhileLoop(
17931942 // zig: b;
17941943 // zig: if (!cond) break;
17951944 // zig: }
1796 break :blk (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
1945 const body = (try transStmt(rp, &loop_scope, ZigClangDoStmt_getBody(stmt), .unused, .r_value)).cast(ast.Node.Block).?;
1946 // if this is used as an expression in Zig it needs to be immediately followed by a semicolon
1947 _ = try appendToken(rp.c, .Semicolon, ";");
1948 break :blk body;
17971949 } else blk: {
17981950 // the C statement is without a block, so we need to create a block to contain it.
17991951 // c: do
......@@ -2026,16 +2178,17 @@ fn transCharLiteral(
20262178 scope: *Scope,
20272179 stmt: *const ZigClangCharacterLiteral,
20282180 result_used: ResultUsed,
2181 suppress_as: SuppressCast,
20292182) TransError!*ast.Node {
20302183 const kind = ZigClangCharacterLiteral_getKind(stmt);
2031 switch (kind) {
2032 .Ascii, .UTF8 => {
2184 const int_lit_node = switch (kind) {
2185 .Ascii, .UTF8 => blk: {
20332186 const val = ZigClangCharacterLiteral_getValue(stmt);
20342187 if (kind == .Ascii) {
20352188 // C has a somewhat obscure feature called multi-character character
20362189 // constant
20372190 if (val > 255)
2038 return transCreateNodeInt(rp.c, val);
2191 break :blk try transCreateNodeInt(rp.c, val);
20392192 }
20402193 var char_buf: [4]u8 = undefined;
20412194 const token = try appendTokenFmt(rp.c, .CharLiteral, "'{}'", .{escapeChar(@intCast(u8, val), &char_buf)});
......@@ -2043,7 +2196,7 @@ fn transCharLiteral(
20432196 node.* = .{
20442197 .token = token,
20452198 };
2046 return maybeSuppressResult(rp, scope, result_used, &node.base);
2199 break :blk &node.base;
20472200 },
20482201 .UTF16, .UTF32, .Wide => return revertAndWarn(
20492202 rp,
......@@ -2053,7 +2206,22 @@ fn transCharLiteral(
20532206 .{kind},
20542207 ),
20552208 else => unreachable,
2209 };
2210 if (suppress_as == .no_as) {
2211 return maybeSuppressResult(rp, scope, result_used, int_lit_node);
20562212 }
2213 // See comment in `transIntegerLiteral` for why this code is here.
2214 // @as(T, x)
2215 const expr_base = @ptrCast(*const ZigClangExpr, stmt);
2216 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
2217 const ty_node = try transQualType(rp, ZigClangExpr_getType(expr_base), ZigClangExpr_getBeginLoc(expr_base));
2218 try as_node.params.push(ty_node);
2219 _ = try appendToken(rp.c, .Comma, ",");
2220
2221 try as_node.params.push(int_lit_node);
2222
2223 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
2224 return maybeSuppressResult(rp, scope, result_used, &as_node.base);
20572225}
20582226
20592227fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr, used: ResultUsed) TransError!*ast.Node {
......@@ -2096,6 +2264,9 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE
20962264 }
20972265
20982266 const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, ZigClangMemberExpr_getMemberDecl(stmt))));
2267 if (name.len == 0) {
2268 return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)), "TODO access of anonymous field", .{});
2269 }
20992270 const node = try transCreateNodeFieldAccess(rp.c, container_node, name);
21002271 return maybeSuppressResult(rp, scope, result_used, node);
21012272}
......@@ -2208,32 +2379,32 @@ fn transUnaryExprOrTypeTraitExpr(
22082379 return maybeSuppressResult(rp, scope, result_used, &builtin_node.base);
22092380}
22102381
2211fn qualTypeHaswrappingOverflow(qt: ZigClangQualType) bool {
2212 if (cIsSignedInteger(qt) or cIsFloating(qt)) {
2213 // float and signed integer overflow is undefined behavior.
2214 return false;
2215 } else {
2382fn qualTypeHasWrappingOverflow(qt: ZigClangQualType) bool {
2383 if (cIsUnsignedInteger(qt)) {
22162384 // unsigned integer overflow wraps around.
22172385 return true;
2386 } else {
2387 // float, signed integer, and pointer overflow is undefined behavior.
2388 return false;
22182389 }
22192390}
22202391
22212392fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnaryOperator, used: ResultUsed) TransError!*ast.Node {
22222393 const op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
22232394 switch (ZigClangUnaryOperator_getOpcode(stmt)) {
2224 .PostInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2395 .PostInc => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22252396 return transCreatePostCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
22262397 else
22272398 return transCreatePostCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
2228 .PostDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2399 .PostDec => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22292400 return transCreatePostCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
22302401 else
22312402 return transCreatePostCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
2232 .PreInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2403 .PreInc => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22332404 return transCreatePreCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
22342405 else
22352406 return transCreatePreCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
2236 .PreDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2407 .PreDec => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22372408 return transCreatePreCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
22382409 else
22392410 return transCreatePreCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
......@@ -2253,7 +2424,7 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
22532424 },
22542425 .Plus => return transExpr(rp, scope, op_expr, used, .r_value),
22552426 .Minus => {
2256 if (!qualTypeHaswrappingOverflow(ZigClangExpr_getType(op_expr))) {
2427 if (!qualTypeHasWrappingOverflow(ZigClangExpr_getType(op_expr))) {
22572428 const op_node = try transCreateNodePrefixOp(rp.c, .Negation, .Minus, "-");
22582429 op_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value);
22592430 return &op_node.base;
......@@ -2313,7 +2484,7 @@ fn transCreatePreCrement(
23132484 // zig: })
23142485 const block_scope = try Scope.Block.init(rp.c, scope, "blk");
23152486 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
2316 const ref = try std.fmt.allocPrint(rp.c.a(), "_ref_{}", .{rp.c.getMangle()});
2487 const ref = try block_scope.makeMangledName(rp.c, "ref");
23172488
23182489 const node = try transCreateNodeVarDecl(rp.c, false, true, ref);
23192490 node.eq_token = try appendToken(rp.c, .Equal, "=");
......@@ -2378,7 +2549,7 @@ fn transCreatePostCrement(
23782549 // zig: })
23792550 const block_scope = try Scope.Block.init(rp.c, scope, "blk");
23802551 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
2381 const ref = try std.fmt.allocPrint(rp.c.a(), "_ref_{}", .{rp.c.getMangle()});
2552 const ref = try block_scope.makeMangledName(rp.c, "ref");
23822553
23832554 const node = try transCreateNodeVarDecl(rp.c, false, true, ref);
23842555 node.eq_token = try appendToken(rp.c, .Equal, "=");
......@@ -2392,7 +2563,7 @@ fn transCreatePostCrement(
23922563 const ref_node = try transCreateNodePtrDeref(rp.c, lhs_node);
23932564 _ = try appendToken(rp.c, .Semicolon, ";");
23942565
2395 const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()});
2566 const tmp = try block_scope.makeMangledName(rp.c, "tmp");
23962567 const tmp_node = try transCreateNodeVarDecl(rp.c, false, true, tmp);
23972568 tmp_node.eq_token = try appendToken(rp.c, .Equal, "=");
23982569 tmp_node.init_node = ref_node;
......@@ -2421,15 +2592,15 @@ fn transCreatePostCrement(
24212592
24222593fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
24232594 switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
2424 .MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2595 .MulAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
24252596 return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MulWrap, .AsteriskPercent, "*%", used)
24262597 else
24272598 return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used),
2428 .AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2599 .AddAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
24292600 return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
24302601 else
24312602 return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used),
2432 .SubAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2603 .SubAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
24332604 return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
24342605 else
24352606 return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
......@@ -2470,7 +2641,10 @@ fn transCreateCompoundAssign(
24702641 // zig: lhs += rhs
24712642 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
24722643 const eq_token = try appendToken(rp.c, assign_tok_id, assign_bytes);
2473 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
2644 var rhs_node = if (is_shift)
2645 try transExprCoercing(rp, scope, rhs, .used, .r_value)
2646 else
2647 try transExpr(rp, scope, rhs, .used, .r_value);
24742648
24752649 if (is_shift) {
24762650 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
......@@ -2494,7 +2668,7 @@ fn transCreateCompoundAssign(
24942668 // zig: })
24952669 const block_scope = try Scope.Block.init(rp.c, scope, "blk");
24962670 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
2497 const ref = try std.fmt.allocPrint(rp.c.a(), "_ref_{}", .{rp.c.getMangle()});
2671 const ref = try block_scope.makeMangledName(rp.c, "ref");
24982672
24992673 const node = try transCreateNodeVarDecl(rp.c, false, true, ref);
25002674 node.eq_token = try appendToken(rp.c, .Equal, "=");
......@@ -2671,6 +2845,30 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
26712845 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
26722846}
26732847
2848/// Produces a Zig AST node by translating a Clang QualType, respecting the width, but modifying the signed-ness.
2849/// Asserts the type is an integer.
2850fn transQualTypeIntWidthOf(c: *Context, ty: ZigClangQualType, is_signed: bool) TypeError!*ast.Node {
2851 return transTypeIntWidthOf(c, qualTypeCanon(ty), is_signed);
2852}
2853
2854/// Produces a Zig AST node by translating a Clang Type, respecting the width, but modifying the signed-ness.
2855/// Asserts the type is an integer.
2856fn transTypeIntWidthOf(c: *Context, ty: *const ZigClangType, is_signed: bool) TypeError!*ast.Node {
2857 assert(ZigClangType_getTypeClass(ty) == .Builtin);
2858 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
2859 return transCreateNodeIdentifier(c, switch (ZigClangBuiltinType_getKind(builtin_ty)) {
2860 .Char_U, .Char_S, .UChar, .SChar, .Char8 => if (is_signed) "i8" else "u8",
2861 .UShort, .Short => if (is_signed) "c_short" else "c_ushort",
2862 .UInt, .Int => if (is_signed) "c_int" else "c_uint",
2863 .ULong, .Long => if (is_signed) "c_long" else "c_ulong",
2864 .ULongLong, .LongLong => if (is_signed) "c_longlong" else "c_ulonglong",
2865 .UInt128, .Int128 => if (is_signed) "i128" else "u128",
2866 .Char16 => if (is_signed) "i16" else "u16",
2867 .Char32 => if (is_signed) "i32" else "u32",
2868 else => unreachable, // only call this function when it has already been determined the type is int
2869 });
2870}
2871
26742872fn isCBuiltinType(qt: ZigClangQualType, kind: ZigClangBuiltinTypeKind) bool {
26752873 const c_type = qualTypeCanon(qt);
26762874 if (ZigClangType_getTypeClass(c_type) != .Builtin)
......@@ -2732,7 +2930,7 @@ fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigC
27322930
27332931 if (int_bit_width != 0) {
27342932 // we can perform the log2 now.
2735 const cast_bit_width = std.math.log2_int(u64, int_bit_width);
2933 const cast_bit_width = math.log2_int(u64, int_bit_width);
27362934 const node = try rp.c.a().create(ast.Node.IntegerLiteral);
27372935 node.* = ast.Node.IntegerLiteral{
27382936 .token = try appendTokenFmt(rp.c, .Identifier, "u{}", .{cast_bit_width}),
......@@ -2869,6 +3067,10 @@ fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocatio
28693067 }
28703068}
28713069
3070fn cIsInteger(qt: ZigClangQualType) bool {
3071 return cIsSignedInteger(qt) or cIsUnsignedInteger(qt);
3072}
3073
28723074fn cIsUnsignedInteger(qt: ZigClangQualType) bool {
28733075 const c_type = qualTypeCanon(qt);
28743076 if (ZigClangType_getTypeClass(c_type) != .Builtin) return false;
......@@ -2888,6 +3090,28 @@ fn cIsUnsignedInteger(qt: ZigClangQualType) bool {
28883090 };
28893091}
28903092
3093fn cIntTypeToIndex(qt: ZigClangQualType) u8 {
3094 const c_type = qualTypeCanon(qt);
3095 assert(ZigClangType_getTypeClass(c_type) == .Builtin);
3096 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
3097 return switch (ZigClangBuiltinType_getKind(builtin_ty)) {
3098 .Bool, .Char_U, .Char_S, .UChar, .SChar, .Char8 => 1,
3099 .WChar_U, .WChar_S => 2,
3100 .UShort, .Short, .Char16 => 3,
3101 .UInt, .Int, .Char32 => 4,
3102 .ULong, .Long => 5,
3103 .ULongLong, .LongLong => 6,
3104 .UInt128, .Int128 => 7,
3105 else => unreachable,
3106 };
3107}
3108
3109fn cIntTypeCmp(a: ZigClangQualType, b: ZigClangQualType) math.Order {
3110 const a_index = cIntTypeToIndex(a);
3111 const b_index = cIntTypeToIndex(b);
3112 return math.order(a_index, b_index);
3113}
3114
28913115fn cIsSignedInteger(qt: ZigClangQualType) bool {
28923116 const c_type = qualTypeCanon(qt);
28933117 if (ZigClangType_getTypeClass(c_type) != .Builtin) return false;
......@@ -2932,7 +3156,7 @@ fn transCreateNodeAssign(
29323156 if (result_used == .unused) {
29333157 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
29343158 const eq_token = try appendToken(rp.c, .Equal, "=");
2935 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
3159 var rhs_node = try transExprCoercing(rp, scope, rhs, .used, .r_value);
29363160 if (isBoolRes(rhs_node)) {
29373161 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");
29383162 try builtin_node.params.push(rhs_node);
......@@ -2953,11 +3177,11 @@ fn transCreateNodeAssign(
29533177 // zig: })
29543178 const block_scope = try Scope.Block.init(rp.c, scope, "blk");
29553179 block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label);
2956 const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()});
3180 const tmp = try block_scope.makeMangledName(rp.c, "tmp");
29573181
29583182 const node = try transCreateNodeVarDecl(rp.c, false, true, tmp);
29593183 node.eq_token = try appendToken(rp.c, .Equal, "=");
2960 var rhs_node = try transExpr(rp, scope, rhs, .used, .r_value);
3184 var rhs_node = try transExpr(rp, &block_scope.base, rhs, .used, .r_value);
29613185 if (isBoolRes(rhs_node)) {
29623186 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@boolToInt");
29633187 try builtin_node.params.push(rhs_node);
......@@ -2968,12 +3192,12 @@ fn transCreateNodeAssign(
29683192 node.semicolon_token = try appendToken(rp.c, .Semicolon, ";");
29693193 try block_scope.block_node.statements.push(&node.base);
29703194
2971 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
3195 const lhs_node = try transExpr(rp, &block_scope.base, lhs, .used, .l_value);
29723196 const eq_token = try appendToken(rp.c, .Equal, "=");
29733197 const ident = try transCreateNodeIdentifier(rp.c, tmp);
29743198 _ = try appendToken(rp.c, .Semicolon, ";");
29753199
2976 const assign = try transCreateNodeInfixOp(rp, scope, lhs_node, .Assign, eq_token, ident, .used, false);
3200 const assign = try transCreateNodeInfixOp(rp, &block_scope.base, lhs_node, .Assign, eq_token, ident, .used, false);
29773201 try block_scope.block_node.statements.push(assign);
29783202
29793203 const break_node = try transCreateNodeBreak(rp.c, block_scope.label);
......@@ -3144,7 +3368,7 @@ fn transCreateNodeAPInt(c: *Context, int: *const ZigClangAPSInt) !*ast.Node {
31443368 const is_negative = ZigClangAPSInt_isSigned(int) and ZigClangAPSInt_isNegative(int);
31453369 if (is_negative)
31463370 aps_int = ZigClangAPSInt_negate(aps_int);
3147 var big = try std.math.big.Int.initCapacity(c.a(), num_limbs);
3371 var big = try math.big.Int.initCapacity(c.a(), num_limbs);
31483372 if (is_negative)
31493373 big.negate();
31503374 defer big.deinit();
......@@ -3508,7 +3732,7 @@ fn transCreateNodeShiftOp(
35083732 const rhs_type = try qualTypeToLog2IntRef(rp, ZigClangBinaryOperator_getType(stmt), rhs_location);
35093733 try as_node.params.push(rhs_type);
35103734 _ = try appendToken(rp.c, .Comma, ",");
3511 const rhs = try transExpr(rp, scope, rhs_expr, .used, .r_value);
3735 const rhs = try transExprCoercing(rp, scope, rhs_expr, .used, .r_value);
35123736 try as_node.params.push(rhs);
35133737 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
35143738
......@@ -3638,7 +3862,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
36383862 const const_arr_ty = @ptrCast(*const ZigClangConstantArrayType, ty);
36393863
36403864 const size_ap_int = ZigClangConstantArrayType_getSize(const_arr_ty);
3641 const size = ZigClangAPInt_getLimitedValue(size_ap_int, std.math.maxInt(usize));
3865 const size = ZigClangAPInt_getLimitedValue(size_ap_int, math.maxInt(usize));
36423866 var node = try transCreateNodePrefixOp(
36433867 rp.c,
36443868 .{
......@@ -4072,7 +4296,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
40724296 var it = ZigClangASTUnit_getLocalPreprocessingEntities_begin(unit);
40734297 const it_end = ZigClangASTUnit_getLocalPreprocessingEntities_end(unit);
40744298 var tok_list = ctok.TokenList.init(c.a());
4075 const scope = &c.global_scope.base;
4299 const scope = c.global_scope;
40764300
40774301 while (it.I != it_end.I) : (it.I += 1) {
40784302 const entity = ZigClangPreprocessingRecord_iterator_deref(it);
......@@ -4084,15 +4308,15 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
40844308 const begin_loc = ZigClangMacroDefinitionRecord_getSourceRange_getBegin(macro);
40854309
40864310 const name = try c.str(raw_name);
4087
40884311 // TODO https://github.com/ziglang/zig/issues/3756
40894312 // TODO https://github.com/ziglang/zig/issues/1802
4090 const checked_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "_{}", .{name}) else name;
4091 if (scope.contains(checked_name)) {
4313 const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "_{}", .{name}) else name;
4314 if (scope.containsNow(mangled_name)) {
40924315 continue;
40934316 }
4317
40944318 const begin_c = ZigClangSourceManager_getCharacterData(c.source_manager, begin_loc);
4095 ctok.tokenizeCMacro(c, begin_loc, checked_name, &tok_list, begin_c) catch |err| switch (err) {
4319 ctok.tokenizeCMacro(c, begin_loc, mangled_name, &tok_list, begin_c) catch |err| switch (err) {
40964320 error.OutOfMemory => |e| return e,
40974321 else => {
40984322 continue;
......@@ -4107,7 +4331,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
41074331 .Identifier => {
41084332 // if it equals itself, ignore. for example, from stdio.h:
41094333 // #define stdin stdin
4110 if (mem.eql(u8, checked_name, next.bytes)) {
4334 if (mem.eql(u8, name, next.bytes)) {
41114335 continue;
41124336 }
41134337 },
......@@ -4118,15 +4342,16 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
41184342 },
41194343 else => {},
41204344 }
4345
41214346 const macro_fn = if (tok_it.peek().?.id == .Fn) blk: {
41224347 _ = tok_it.next();
41234348 break :blk true;
41244349 } else false;
41254350
41264351 (if (macro_fn)
4127 transMacroFnDefine(c, &tok_it, checked_name, begin_loc)
4352 transMacroFnDefine(c, &tok_it, mangled_name, begin_loc)
41284353 else
4129 transMacroDefine(c, &tok_it, checked_name, begin_loc)) catch |err| switch (err) {
4354 transMacroDefine(c, &tok_it, mangled_name, begin_loc)) catch |err| switch (err) {
41304355 error.ParseError => continue,
41314356 error.OutOfMemory => |e| return e,
41324357 };
......@@ -4189,12 +4414,8 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
41894414 );
41904415 }
41914416
4192 const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {
4193 try block_scope.variables.push(.{ .name = param_tok.bytes, .alias = alias });
4194 break :blk alias;
4195 } else param_tok.bytes;
4196
4197 const param_name_tok = try appendIdentifier(c, checked_name);
4417 const mangled_name = try block_scope.makeMangledName(c, param_tok.bytes);
4418 const param_name_tok = try appendIdentifier(c, mangled_name);
41984419 _ = try appendToken(c, .Colon, ":");
41994420
42004421 const token_index = try appendToken(c, .Keyword_var, "var");
......@@ -4234,7 +4455,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
42344455 _ = try appendToken(c, .RParen, ")");
42354456
42364457 const type_of = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
4237 type_of.rparen_token = try appendToken(c, .LParen, ")");
4458 type_of.rparen_token = try appendToken(c, .RParen, ")");
42384459
42394460 const fn_proto = try c.a().create(ast.Node.FnProto);
42404461 fn_proto.* = .{
......@@ -4279,7 +4500,33 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
42794500const ParseError = Error || error{ParseError};
42804501
42814502fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
4282 return parseCPrefixOpExpr(c, it, source_loc, scope);
4503 const node = try parseCPrefixOpExpr(c, it, source_loc, scope);
4504 switch (it.next().?.id) {
4505 .QuestionMark => {
4506 // must come immediately after expr
4507 _ = try appendToken(c, .RParen, ")");
4508 const if_node = try transCreateNodeIf(c);
4509 if_node.condition = node;
4510 if_node.body = try parseCPrimaryExpr(c, it, source_loc, scope);
4511 if (it.next().?.id != .Colon) {
4512 try failDecl(
4513 c,
4514 source_loc,
4515 it.list.at(0).*.bytes,
4516 "unable to translate C expr: expected ':'",
4517 .{},
4518 );
4519 return error.ParseError;
4520 }
4521 if_node.@"else" = try transCreateNodeElse(c);
4522 if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source_loc, scope);
4523 return &if_node.base;
4524 },
4525 else => {
4526 _ = it.prev();
4527 return node;
4528 },
4529 }
42834530}
42844531
42854532fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {
......@@ -4349,8 +4596,8 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC
43494596 return parseCNumLit(c, tok, source_loc);
43504597 },
43514598 .Identifier => {
4352 const name = if (scope.getAlias(tok.bytes)) |a| a else tok.bytes;
4353 return transCreateNodeIdentifier(c, name);
4599 const mangled_name = scope.getAlias(tok.bytes);
4600 return transCreateNodeIdentifier(c, mangled_name);
43544601 },
43554602 .LParen => {
43564603 const inner_node = try parseCExpr(c, it, source_loc, scope);
......@@ -4391,8 +4638,8 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC
43914638 const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
43924639 try type_id_1.params.push(&type_of_1.base);
43934640 try type_of_1.params.push(node_to_cast);
4394 type_of_1.rparen_token = try appendToken(c, .LParen, ")");
4395 type_id_1.rparen_token = try appendToken(c, .LParen, ")");
4641 type_of_1.rparen_token = try appendToken(c, .RParen, ")");
4642 type_id_1.rparen_token = try appendToken(c, .RParen, ")");
43964643
43974644 const cmp_1 = try c.a().create(ast.Node.InfixOp);
43984645 cmp_1.* = .{
......@@ -4402,12 +4649,12 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC
44024649 .rhs = try transCreateNodeEnumLiteral(c, "Pointer"),
44034650 };
44044651 if_1.condition = &cmp_1.base;
4405 _ = try appendToken(c, .LParen, ")");
4652 _ = try appendToken(c, .RParen, ")");
44064653
44074654 const ptr_cast = try transCreateNodeBuiltinFnCall(c, "@ptrCast");
44084655 try ptr_cast.params.push(inner_node);
44094656 try ptr_cast.params.push(node_to_cast);
4410 ptr_cast.rparen_token = try appendToken(c, .LParen, ")");
4657 ptr_cast.rparen_token = try appendToken(c, .RParen, ")");
44114658 if_1.body = &ptr_cast.base;
44124659
44134660 const else_1 = try transCreateNodeElse(c);
......@@ -4418,8 +4665,8 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC
44184665 const type_of_2 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
44194666 try type_id_2.params.push(&type_of_2.base);
44204667 try type_of_2.params.push(node_to_cast);
4421 type_of_2.rparen_token = try appendToken(c, .LParen, ")");
4422 type_id_2.rparen_token = try appendToken(c, .LParen, ")");
4668 type_of_2.rparen_token = try appendToken(c, .RParen, ")");
4669 type_id_2.rparen_token = try appendToken(c, .RParen, ")");
44234670
44244671 const cmp_2 = try c.a().create(ast.Node.InfixOp);
44254672 cmp_2.* = .{
......@@ -4430,12 +4677,12 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC
44304677 };
44314678 if_2.condition = &cmp_2.base;
44324679 else_1.body = &if_2.base;
4433 _ = try appendToken(c, .LParen, ")");
4680 _ = try appendToken(c, .RParen, ")");
44344681
44354682 const int_to_ptr = try transCreateNodeBuiltinFnCall(c, "@intToPtr");
44364683 try int_to_ptr.params.push(inner_node);
44374684 try int_to_ptr.params.push(node_to_cast);
4438 int_to_ptr.rparen_token = try appendToken(c, .LParen, ")");
4685 int_to_ptr.rparen_token = try appendToken(c, .RParen, ")");
44394686 if_2.body = &int_to_ptr.base;
44404687
44414688 const else_2 = try transCreateNodeElse(c);
......@@ -4444,7 +4691,7 @@ fn parseCPrimaryExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigC
44444691 const as = try transCreateNodeBuiltinFnCall(c, "@as");
44454692 try as.params.push(inner_node);
44464693 try as.params.push(node_to_cast);
4447 as.rparen_token = try appendToken(c, .LParen, ")");
4694 as.rparen_token = try appendToken(c, .RParen, ")");
44484695 else_2.body = &as.base;
44494696
44504697 return &if_1.base;
......@@ -4524,7 +4771,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig
45244771 },
45254772 .Shl => {
45264773 const op_token = try appendToken(c, .AngleBracketAngleBracketLeft, "<<");
4527 const rhs = try parseCExpr(c, it, source_loc, scope);
4774 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
45284775 const bitshift_node = try c.a().create(ast.Node.InfixOp);
45294776 bitshift_node.* = .{
45304777 .op_token = op_token,
......@@ -4534,9 +4781,21 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig
45344781 };
45354782 node = &bitshift_node.base;
45364783 },
4784 .Shr => {
4785 const op_token = try appendToken(c, .AngleBracketAngleBracketRight, ">>");
4786 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4787 const bitshift_node = try c.a().create(ast.Node.InfixOp);
4788 bitshift_node.* = .{
4789 .op_token = op_token,
4790 .lhs = node,
4791 .op = .BitShiftRight,
4792 .rhs = rhs,
4793 };
4794 node = &bitshift_node.base;
4795 },
45374796 .Pipe => {
45384797 const op_token = try appendToken(c, .Pipe, "|");
4539 const rhs = try parseCExpr(c, it, source_loc, scope);
4798 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
45404799 const or_node = try c.a().create(ast.Node.InfixOp);
45414800 or_node.* = .{
45424801 .op_token = op_token,
......@@ -4546,9 +4805,117 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig
45464805 };
45474806 node = &or_node.base;
45484807 },
4808 .Ampersand => {
4809 const op_token = try appendToken(c, .Ampersand, "&");
4810 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4811 const bitand_node = try c.a().create(ast.Node.InfixOp);
4812 bitand_node.* = .{
4813 .op_token = op_token,
4814 .lhs = node,
4815 .op = .BitAnd,
4816 .rhs = rhs,
4817 };
4818 node = &bitand_node.base;
4819 },
4820 .Plus => {
4821 const op_token = try appendToken(c, .Plus, "+");
4822 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4823 const add_node = try c.a().create(ast.Node.InfixOp);
4824 add_node.* = .{
4825 .op_token = op_token,
4826 .lhs = node,
4827 .op = .Add,
4828 .rhs = rhs,
4829 };
4830 node = &add_node.base;
4831 },
4832 .Minus => {
4833 const op_token = try appendToken(c, .Minus, "-");
4834 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4835 const sub_node = try c.a().create(ast.Node.InfixOp);
4836 sub_node.* = .{
4837 .op_token = op_token,
4838 .lhs = node,
4839 .op = .Sub,
4840 .rhs = rhs,
4841 };
4842 node = &sub_node.base;
4843 },
4844 .And => {
4845 const op_token = try appendToken(c, .Keyword_and, "and");
4846 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4847 const and_node = try c.a().create(ast.Node.InfixOp);
4848 and_node.* = .{
4849 .op_token = op_token,
4850 .lhs = node,
4851 .op = .BoolAnd,
4852 .rhs = rhs,
4853 };
4854 node = &and_node.base;
4855 },
4856 .Or => {
4857 const op_token = try appendToken(c, .Keyword_or, "or");
4858 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4859 const or_node = try c.a().create(ast.Node.InfixOp);
4860 or_node.* = .{
4861 .op_token = op_token,
4862 .lhs = node,
4863 .op = .BoolOr,
4864 .rhs = rhs,
4865 };
4866 node = &or_node.base;
4867 },
4868 .Gt => {
4869 const op_token = try appendToken(c, .AngleBracketRight, ">");
4870 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4871 const and_node = try c.a().create(ast.Node.InfixOp);
4872 and_node.* = .{
4873 .op_token = op_token,
4874 .lhs = node,
4875 .op = .GreaterThan,
4876 .rhs = rhs,
4877 };
4878 node = &and_node.base;
4879 },
4880 .Gte => {
4881 const op_token = try appendToken(c, .AngleBracketRightEqual, ">=");
4882 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4883 const and_node = try c.a().create(ast.Node.InfixOp);
4884 and_node.* = .{
4885 .op_token = op_token,
4886 .lhs = node,
4887 .op = .GreaterOrEqual,
4888 .rhs = rhs,
4889 };
4890 node = &and_node.base;
4891 },
4892 .Lt => {
4893 const op_token = try appendToken(c, .AngleBracketLeft, "<");
4894 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4895 const and_node = try c.a().create(ast.Node.InfixOp);
4896 and_node.* = .{
4897 .op_token = op_token,
4898 .lhs = node,
4899 .op = .LessThan,
4900 .rhs = rhs,
4901 };
4902 node = &and_node.base;
4903 },
4904 .Lte => {
4905 const op_token = try appendToken(c, .AngleBracketLeftEqual, "<=");
4906 const rhs = try parseCPrefixOpExpr(c, it, source_loc, scope);
4907 const and_node = try c.a().create(ast.Node.InfixOp);
4908 and_node.* = .{
4909 .op_token = op_token,
4910 .lhs = node,
4911 .op = .LessOrEqual,
4912 .rhs = rhs,
4913 };
4914 node = &and_node.base;
4915 },
45494916 .LBrace => {
45504917 const arr_node = try transCreateNodeArrayAccess(c, node);
4551 arr_node.op.ArrayAccess = try parseCExpr(c, it, source_loc, scope);
4918 arr_node.op.ArrayAccess = try parseCPrefixOpExpr(c, it, source_loc, scope);
45524919 arr_node.rtoken = try appendToken(c, .RBrace, "]");
45534920 node = &arr_node.base;
45544921 if (it.next().?.id != .RBrace) {
......@@ -4565,7 +4932,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig
45654932 .LParen => {
45664933 const call_node = try transCreateNodeFnCall(c, node);
45674934 while (true) {
4568 const arg = try parseCExpr(c, it, source_loc, scope);
4935 const arg = try parseCPrefixOpExpr(c, it, source_loc, scope);
45694936 try call_node.op.Call.params.push(arg);
45704937 const next = it.next().?;
45714938 if (next.id == .Comma)
......@@ -4586,26 +4953,6 @@ fn parseCSuffixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig
45864953 call_node.rtoken = try appendToken(c, .RParen, ")");
45874954 node = &call_node.base;
45884955 },
4589 .QuestionMark => {
4590 // must come immediately after expr
4591 _ = try appendToken(c, .RParen, ")");
4592 const if_node = try transCreateNodeIf(c);
4593 if_node.condition = node;
4594 if_node.body = try parseCPrimaryExpr(c, it, source_loc, scope);
4595 if (it.next().?.id != .Colon) {
4596 try failDecl(
4597 c,
4598 source_loc,
4599 it.list.at(0).*.bytes,
4600 "unable to translate C expr: expected ':'",
4601 .{},
4602 );
4603 return error.ParseError;
4604 }
4605 if_node.@"else" = try transCreateNodeElse(c);
4606 if_node.@"else".?.body = try parseCPrimaryExpr(c, it, source_loc, scope);
4607 node = &if_node.base;
4608 },
46094956 else => {
46104957 _ = it.prev();
46114958 return node;
......@@ -4646,7 +4993,11 @@ fn parseCPrefixOpExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: Zig
46464993
46474994fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {
46484995 const tok = c.tree.tokens.at(token);
4649 return c.source_buffer.toSlice()[tok.start..tok.end];
4996 const slice = c.source_buffer.toSlice()[tok.start..tok.end];
4997 return if (mem.startsWith(u8, slice, "@\""))
4998 slice[2 .. slice.len - 1]
4999 else
5000 slice;
46505001}
46515002
46525003fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
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"
......@@ -9104,7 +9103,7 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
91049103
91059104}
91069105
9107void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) {
9106void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file) {
91089107 Error err;
91099108 Buf *src_basename = buf_alloc();
91109109 Buf *src_dirname = buf_alloc();
......@@ -9117,10 +9116,6 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
91179116
91189117 init(g);
91199118
9120 TranslateMode trans_mode = buf_ends_with_str(full_path, ".h") ?
9121 TranslateModeImport : TranslateModeTranslate;
9122
9123
91249119 ZigList<const char *> clang_argv = {0};
91259120 add_cc_args(g, clang_argv, nullptr, true);
91269121
......@@ -9140,15 +9135,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
91409135 Stage2ErrorMsg *errors_ptr;
91419136 size_t errors_len;
91429137 Stage2Ast *ast;
9143 AstNode *root_node;
91449138
9145 if (use_userland_implementation) {
9146 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
9147 &clang_argv.at(0), &clang_argv.last(), resources_path);
9148 } else {
9149 err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
9150 trans_mode, resources_path);
9151 }
9139 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
9140 &clang_argv.at(0), &clang_argv.last(), resources_path);
91529141
91539142 if (err == ErrorCCompileErrors && errors_len > 0) {
91549143 for (size_t i = 0; i < errors_len; i += 1) {
......@@ -9172,12 +9161,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
91729161 exit(1);
91739162 }
91749163
9175
9176 if (use_userland_implementation) {
9177 stage2_render_ast(ast, out_file);
9178 } else {
9179 ast_render(out_file, root_node, 4);
9180 }
9164 stage2_render_ast(ast, out_file);
91819165}
91829166
91839167static 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>
......@@ -23762,14 +23761,14 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
2376223761
2376323762 clang_argv.append(nullptr); // to make the [start...end] argument work
2376423763
23765 AstNode *root_node;
2376623764 Stage2ErrorMsg *errors_ptr;
2376723765 size_t errors_len;
23766 Stage2Ast *ast;
2376823767
2376923768 const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
2377023769
23771 if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
23772 &clang_argv.at(0), &clang_argv.last(), TranslateModeImport, resources_path)))
23770 if ((err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
23771 &clang_argv.at(0), &clang_argv.last(), resources_path)))
2377323772 {
2377423773 if (err != ErrorCCompileErrors) {
2377523774 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
......@@ -23820,7 +23819,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
2382023819 buf_sprintf("C import failed: unable to open output file: %s", strerror(errno)));
2382123820 return ira->codegen->invalid_instruction;
2382223821 }
23823 ast_render(out_file, root_node, 4);
23822 stage2_render_ast(ast, out_file);
2382423823 if (fclose(out_file) != 0) {
2382523824 ir_add_error_node(ira, node,
2382623825 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
src/zig_clang.cpp+10
......@@ -1686,6 +1686,16 @@ const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFun
16861686 return reinterpret_cast<const ZigClangStmt *>(stmt);
16871687}
16881688
1689bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const struct ZigClangFunctionDecl *self) {
1690 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1691 return casted->doesDeclarationForceExternallyVisibleDefinition();
1692}
1693
1694bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *self) {
1695 auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
1696 return casted->isInlineSpecified();
1697}
1698
16891699const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) {
16901700 auto casted = reinterpret_cast<const clang::TypedefType *>(self);
16911701 const clang::TypedefNameDecl *name_decl = casted->getDecl();
src/zig_clang.h+2
......@@ -873,6 +873,8 @@ ZIG_EXTERN_C bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl
873873ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *);
874874ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i);
875875ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *);
876ZIG_EXTERN_C bool ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(const struct ZigClangFunctionDecl *);
877ZIG_EXTERN_C bool ZigClangFunctionDecl_isInlineSpecified(const struct ZigClangFunctionDecl *);
876878
877879ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl);
878880ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl);
test/compare_output.zig+5-1
......@@ -5,7 +5,11 @@ const tests = @import("tests.zig");
55
66pub fn addCases(cases: *tests.CompareOutputContext) void {
77 cases.addC("hello world with libc",
8 \\const c = @cImport(@cInclude("stdio.h"));
8 \\const c = @cImport({
9 \\ // See https://github.com/ziglang/zig/issues/515
10 \\ @cDefine("_NO_CRT_STDIO_INLINE", "1");
11 \\ @cInclude("stdio.h");
12 \\});
913 \\pub export fn main(argc: c_int, argv: [*][*]u8) c_int {
1014 \\ _ = c.puts("Hello, world!");
1115 \\ return 0;
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+471-1353
......@@ -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,23 +11,27 @@ 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;
2418 \\ const int c;
2519 \\ const unsigned d = 440;
20 \\ int e = 10;
21 \\ unsigned int f = 10u;
2622 \\}
2723 , &[_][]const u8{
2824 \\pub export fn foo() void {
2925 \\ var a: c_int = undefined;
30 \\ var b: u8 = @as(u8, 123);
26 \\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
3127 \\ const c: c_int = undefined;
32 \\ const d: c_uint = @as(c_uint, 440);
28 \\ const d: c_uint = @bitCast(c_uint, @as(c_int, 440));
29 \\ var e: c_int = 10;
30 \\ var f: c_uint = 10;
3331 \\}
3432 });
3533
36 cases.addC_both("ignore result, explicit function arguments",
34 cases.add("ignore result, explicit function arguments",
3735 \\void foo(void) {
3836 \\ int a;
3937 \\ 1;
......@@ -45,15 +43,25 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
4543 , &[_][]const u8{
4644 \\pub export fn foo() void {
4745 \\ var a: c_int = undefined;
48 \\ _ = 1;
46 \\ _ = @as(c_int, 1);
4947 \\ _ = "hey";
50 \\ _ = (1 + 1);
51 \\ _ = (1 - 1);
48 \\ _ = (@as(c_int, 1) + @as(c_int, 1));
49 \\ _ = (@as(c_int, 1) - @as(c_int, 1));
5250 \\ a = 1;
5351 \\}
5452 });
5553
56 cases.addC_both("variables",
54 cases.add("function with no prototype",
55 \\int foo() {
56 \\ return 5;
57 \\}
58 , &[_][]const u8{
59 \\pub export fn foo() c_int {
60 \\ return 5;
61 \\}
62 });
63
64 cases.add("variables",
5765 \\extern int extern_var;
5866 \\static const int int_var = 13;
5967 , &[_][]const u8{
......@@ -62,13 +70,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
6270 \\pub const int_var: c_int = 13;
6371 });
6472
65 cases.add_both("const ptr initializer",
73 cases.add("const ptr initializer",
6674 \\static const char *v0 = "0.0.0";
6775 , &[_][]const u8{
6876 \\pub var v0: [*c]const u8 = "0.0.0";
6977 });
7078
71 cases.addC_both("static incomplete array inside function",
79 cases.add("static incomplete array inside function",
7280 \\void foo(void) {
7381 \\ static const char v2[] = "2.2.2";
7482 \\}
......@@ -78,7 +86,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
7886 \\}
7987 });
8088
81 cases.addC_both("simple function definition",
89 cases.add("simple function definition",
8290 \\void foo(void) {}
8391 \\static void bar(void) {}
8492 , &[_][]const u8{
......@@ -86,7 +94,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
8694 \\pub fn bar() void {}
8795 });
8896
89 cases.add_both("typedef void",
97 cases.add("typedef void",
9098 \\typedef void Foo;
9199 \\Foo fun(Foo *a);
92100 , &[_][]const u8{
......@@ -95,7 +103,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
95103 \\pub extern fn fun(a: ?*Foo) Foo;
96104 });
97105
98 cases.add_both("duplicate typedef",
106 cases.add("duplicate typedef",
99107 \\typedef long foo;
100108 \\typedef int bar;
101109 \\typedef long foo;
......@@ -106,7 +114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
106114 \\pub const baz = c_int;
107115 });
108116
109 cases.addC_both("casting pointers to ints and ints to pointers",
117 cases.add("casting pointers to ints and ints to pointers",
110118 \\void foo(void);
111119 \\void bar(void) {
112120 \\ void *func_ptr = foo;
......@@ -116,17 +124,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
116124 \\pub extern fn foo() void;
117125 \\pub export fn bar() void {
118126 \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo);
119 \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr)));
127 \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @intCast(c_ulong, @ptrToInt(func_ptr)));
120128 \\}
121129 });
122130
123 cases.add_both("noreturn attribute",
131 cases.add("noreturn attribute",
124132 \\void foo(void) __attribute__((noreturn));
125133 , &[_][]const u8{
126134 \\pub extern fn foo() noreturn;
127135 });
128136
129 cases.addC_both("add, sub, mul, div, rem",
137 cases.add("add, sub, mul, div, rem",
130138 \\int s() {
131139 \\ int a, b, c;
132140 \\ c = a + b;
......@@ -166,7 +174,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
166174 \\}
167175 });
168176
169 cases.add_both("typedef of function in struct field",
177 cases.add("typedef of function in struct field",
170178 \\typedef void lws_callback_function(void);
171179 \\struct Foo {
172180 \\ void (*func)(void);
......@@ -180,7 +188,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
180188 \\};
181189 });
182190
183 cases.add_both("pointer to struct demoted to opaque due to bit fields",
191 cases.add("pointer to struct demoted to opaque due to bit fields",
184192 \\struct Foo {
185193 \\ unsigned int: 1;
186194 \\};
......@@ -195,13 +203,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
195203 \\};
196204 });
197205
198 cases.add_both("macro with left shift",
206 cases.add("macro with left shift",
199207 \\#define REDISMODULE_READ (1<<0)
200208 , &[_][]const u8{
201209 \\pub const REDISMODULE_READ = 1 << 0;
202210 });
203211
204 cases.add_both("double define struct",
212 cases.add("macro with right shift",
213 \\#define FLASH_SIZE 0x200000UL /* 2 MB */
214 \\#define FLASH_BANK_SIZE (FLASH_SIZE >> 1) /* 1 MB */
215 , &[_][]const u8{
216 \\pub const FLASH_SIZE = @as(c_ulong, 0x200000);
217 ,
218 \\pub const FLASH_BANK_SIZE = FLASH_SIZE >> 1;
219 });
220
221 cases.add("double define struct",
205222 \\typedef struct Bar Bar;
206223 \\typedef struct Foo Foo;
207224 \\
......@@ -226,7 +243,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
226243 \\pub const Bar = struct_Bar;
227244 });
228245
229 cases.add_both("simple struct",
246 cases.add("simple struct",
230247 \\struct Foo {
231248 \\ int x;
232249 \\ char *y;
......@@ -240,7 +257,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
240257 \\pub const Foo = struct_Foo;
241258 });
242259
243 cases.add_both("self referential struct with function pointer",
260 cases.add("self referential struct with function pointer",
244261 \\struct Foo {
245262 \\ void (*derp)(struct Foo *foo);
246263 \\};
......@@ -252,7 +269,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
252269 \\pub const Foo = struct_Foo;
253270 });
254271
255 cases.add_both("struct prototype used in func",
272 cases.add("struct prototype used in func",
256273 \\struct Foo;
257274 \\struct Foo *some_func(struct Foo *foo, int x);
258275 , &[_][]const u8{
......@@ -263,13 +280,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263280 \\pub const Foo = struct_Foo;
264281 });
265282
266 cases.add_both("#define an unsigned integer literal",
283 cases.add("#define an unsigned integer literal",
267284 \\#define CHANNEL_COUNT 24
268285 , &[_][]const u8{
269286 \\pub const CHANNEL_COUNT = 24;
270287 });
271288
272 cases.add_both("#define referencing another #define",
289 cases.add("#define referencing another #define",
273290 \\#define THING2 THING1
274291 \\#define THING1 1234
275292 , &[_][]const u8{
......@@ -278,7 +295,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
278295 \\pub const THING2 = THING1;
279296 });
280297
281 cases.add_both("circular struct definitions",
298 cases.add("circular struct definitions",
282299 \\struct Bar;
283300 \\
284301 \\struct Foo {
......@@ -298,13 +315,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
298315 \\};
299316 });
300317
301 cases.add_both("#define string",
318 cases.add("#define string",
302319 \\#define foo "a string"
303320 , &[_][]const u8{
304321 \\pub const foo = "a string";
305322 });
306323
307 cases.add_both("zig keywords in C code",
324 cases.add("zig keywords in C code",
308325 \\struct comptime {
309326 \\ int defer;
310327 \\};
......@@ -316,13 +333,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
316333 \\pub const @"comptime" = struct_comptime;
317334 });
318335
319 cases.add_both("macro with parens around negative number",
336 cases.add("macro with parens around negative number",
320337 \\#define LUA_GLOBALSINDEX (-10002)
321338 , &[_][]const u8{
322339 \\pub const LUA_GLOBALSINDEX = -10002;
323340 });
324341
325 cases.add_both(
342 cases.add(
326343 "u integer suffix after 0 (zero) in macro definition",
327344 "#define ZERO 0U",
328345 &[_][]const u8{
......@@ -330,7 +347,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
330347 },
331348 );
332349
333 cases.add_both(
350 cases.add(
334351 "l integer suffix after 0 (zero) in macro definition",
335352 "#define ZERO 0L",
336353 &[_][]const u8{
......@@ -338,7 +355,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
338355 },
339356 );
340357
341 cases.add_both(
358 cases.add(
342359 "ul integer suffix after 0 (zero) in macro definition",
343360 "#define ZERO 0UL",
344361 &[_][]const u8{
......@@ -346,7 +363,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
346363 },
347364 );
348365
349 cases.add_both(
366 cases.add(
350367 "lu integer suffix after 0 (zero) in macro definition",
351368 "#define ZERO 0LU",
352369 &[_][]const u8{
......@@ -354,7 +371,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
354371 },
355372 );
356373
357 cases.add_both(
374 cases.add(
358375 "ll integer suffix after 0 (zero) in macro definition",
359376 "#define ZERO 0LL",
360377 &[_][]const u8{
......@@ -362,7 +379,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
362379 },
363380 );
364381
365 cases.add_both(
382 cases.add(
366383 "ull integer suffix after 0 (zero) in macro definition",
367384 "#define ZERO 0ULL",
368385 &[_][]const u8{
......@@ -370,7 +387,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
370387 },
371388 );
372389
373 cases.add_both(
390 cases.add(
374391 "llu integer suffix after 0 (zero) in macro definition",
375392 "#define ZERO 0LLU",
376393 &[_][]const u8{
......@@ -378,7 +395,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
378395 },
379396 );
380397
381 cases.add_both(
398 cases.add(
382399 "bitwise not on u-suffixed 0 (zero) in macro definition",
383400 "#define NOT_ZERO (~0U)",
384401 &[_][]const u8{
......@@ -386,7 +403,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
386403 },
387404 );
388405
389 cases.addC_both("null statements",
406 cases.add("null statements",
390407 \\void foo(void) {
391408 \\ ;;;;;
392409 \\}
......@@ -402,7 +419,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
402419
403420 if (builtin.os != builtin.Os.windows) {
404421 // 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",
422 cases.add("big negative enum init values when C ABI supports long long enums",
406423 \\enum EnumWithInits {
407424 \\ VAL01 = 0,
408425 \\ VAL02 = 1,
......@@ -457,7 +474,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
457474 });
458475 }
459476
460 cases.addC_both("predefined expressions",
477 cases.add("predefined expressions",
461478 \\void foo(void) {
462479 \\ __func__;
463480 \\ __FUNCTION__;
......@@ -471,39 +488,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
471488 \\}
472489 });
473490
474 cases.addC_both("ignore result, no function arguments",
475 \\void foo() {
476 \\ int a;
477 \\ 1;
478 \\ "hey";
479 \\ 1 + 1;
480 \\ 1 - 1;
481 \\ a = 1;
482 \\}
483 , &[_][]const u8{
484 \\pub export fn foo() void {
485 \\ var a: c_int = undefined;
486 \\ _ = 1;
487 \\ _ = "hey";
488 \\ _ = (1 + 1);
489 \\ _ = (1 - 1);
490 \\ a = 1;
491 \\}
492 });
493
494 cases.add_both("constant size array",
491 cases.add("constant size array",
495492 \\void func(int array[20]);
496493 , &[_][]const u8{
497494 \\pub extern fn func(array: [*c]c_int) void;
498495 });
499496
500 cases.add_both("__cdecl doesn't mess up function pointers",
497 cases.add("__cdecl doesn't mess up function pointers",
501498 \\void foo(void (__cdecl *fn_ptr)(void));
502499 , &[_][]const u8{
503500 \\pub extern fn foo(fn_ptr: ?extern fn () void) void;
504501 });
505502
506 cases.addC_both("void cast",
503 cases.add("void cast",
507504 \\void foo() {
508505 \\ int a;
509506 \\ (void) a;
......@@ -515,7 +512,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
515512 \\}
516513 });
517514
518 cases.addC_both("implicit cast to void *",
515 cases.add("implicit cast to void *",
519516 \\void *foo() {
520517 \\ unsigned short *x;
521518 \\ return x;
......@@ -527,7 +524,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
527524 \\}
528525 });
529526
530 cases.addC_both("null pointer implicit cast",
527 cases.add("null pointer implicit cast",
531528 \\int* foo(void) {
532529 \\ return 0;
533530 \\}
......@@ -537,7 +534,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
537534 \\}
538535 });
539536
540 cases.add_both("simple union",
537 cases.add("simple union",
541538 \\union Foo {
542539 \\ int x;
543540 \\ double y;
......@@ -551,7 +548,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
551548 \\pub const Foo = union_Foo;
552549 });
553550
554 cases.addC_both("string literal",
551 cases.add("string literal",
555552 \\const char *foo(void) {
556553 \\ return "bar";
557554 \\}
......@@ -561,7 +558,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
561558 \\}
562559 });
563560
564 cases.addC_both("return void",
561 cases.add("return void",
565562 \\void foo(void) {
566563 \\ return;
567564 \\}
......@@ -571,7 +568,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
571568 \\}
572569 });
573570
574 cases.addC_both("for loop",
571 cases.add("for loop",
575572 \\void foo(void) {
576573 \\ for (int i = 0; i; i = i + 1) { }
577574 \\}
......@@ -579,12 +576,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
579576 \\pub export fn foo() void {
580577 \\ {
581578 \\ var i: c_int = 0;
582 \\ while (i != 0) : (i = (i + 1)) {}
579 \\ while (i != 0) : (i = (i + @as(c_int, 1))) {}
583580 \\ }
584581 \\}
585582 });
586583
587 cases.addC_both("empty for loop",
584 cases.add("empty for loop",
588585 \\void foo(void) {
589586 \\ for (;;) { }
590587 \\}
......@@ -594,7 +591,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
594591 \\}
595592 });
596593
597 cases.addC_both("break statement",
594 cases.add("break statement",
598595 \\void foo(void) {
599596 \\ for (;;) {
600597 \\ break;
......@@ -608,7 +605,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
608605 \\}
609606 });
610607
611 cases.addC_both("continue statement",
608 cases.add("continue statement",
612609 \\void foo(void) {
613610 \\ for (;;) {
614611 \\ continue;
......@@ -622,7 +619,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
622619 \\}
623620 });
624621
625 cases.addC_both("pointer casting",
622 cases.add("pointer casting",
626623 \\float *ptrcast() {
627624 \\ int *a;
628625 \\ return (float *)a;
......@@ -634,7 +631,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
634631 \\}
635632 });
636633
637 cases.addC_both("pointer conversion with different alignment",
634 cases.add("pointer conversion with different alignment",
638635 \\void test_ptr_cast() {
639636 \\ void *p;
640637 \\ {
......@@ -668,7 +665,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
668665 \\}
669666 });
670667
671 cases.addC_both("while on non-bool",
668 cases.add("while on non-bool",
672669 \\int while_none_bool() {
673670 \\ int a;
674671 \\ float b;
......@@ -690,7 +687,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
690687 \\}
691688 });
692689
693 cases.addC_both("for on non-bool",
690 cases.add("for on non-bool",
694691 \\int for_none_bool() {
695692 \\ int a;
696693 \\ float b;
......@@ -712,17 +709,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
712709 \\}
713710 });
714711
715 cases.addC_both("bitshift",
712 cases.add("bitshift",
716713 \\int foo(void) {
717714 \\ return (1 << 2) >> 1;
718715 \\}
719716 , &[_][]const u8{
720717 \\pub export fn foo() c_int {
721 \\ return (1 << @as(@import("std").math.Log2Int(c_int), 2)) >> @as(@import("std").math.Log2Int(c_int), 1);
718 \\ return (@as(c_int, 1) << @as(@import("std").math.Log2Int(c_int), 2)) >> @as(@import("std").math.Log2Int(c_int), 1);
722719 \\}
723720 });
724721
725 cases.addC_both("sizeof",
722 cases.add("sizeof",
726723 \\#include <stddef.h>
727724 \\size_t size_of(void) {
728725 \\ return sizeof(int);
......@@ -733,7 +730,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
733730 \\}
734731 });
735732
736 cases.addC_both("normal deref",
733 cases.add("normal deref",
737734 \\void foo() {
738735 \\ int *x;
739736 \\ *x = 1;
......@@ -745,7 +742,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
745742 \\}
746743 });
747744
748 cases.addC_both("address of operator",
745 cases.add("address of operator",
749746 \\int foo(void) {
750747 \\ int x = 1234;
751748 \\ int *ptr = &x;
......@@ -759,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
759756 \\}
760757 });
761758
762 cases.addC_both("bin not",
759 cases.add("bin not",
763760 \\int foo() {
764761 \\ int x;
765762 \\ return ~x;
......@@ -771,7 +768,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
771768 \\}
772769 });
773770
774 cases.addC_both("bool not",
771 cases.add("bool not",
775772 \\int foo() {
776773 \\ int a;
777774 \\ float b;
......@@ -786,14 +783,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
786783 \\ var a: c_int = undefined;
787784 \\ var b: f32 = undefined;
788785 \\ var c: ?*c_void = undefined;
789 \\ return !(a == 0);
786 \\ return !(a == @as(c_int, 0));
790787 \\ return !(a != 0);
791788 \\ return !(b != 0);
792789 \\ return !(c != null);
793790 \\}
794791 });
795792
796 cases.addC("__extension__ cast",
793 cases.add("__extension__ cast",
797794 \\int foo(void) {
798795 \\ return __extension__ 1;
799796 \\}
......@@ -805,16 +802,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
805802
806803 if (builtin.os != builtin.Os.windows) {
807804 // sysv_abi not currently supported on windows
808 cases.add_both("Macro qualified functions",
805 cases.add("Macro qualified functions",
809806 \\void __attribute__((sysv_abi)) foo(void);
810807 , &[_][]const u8{
811808 \\pub extern fn foo() void;
812809 });
813810 }
814811
815 /////////////// Cases that pass for only stage2 ////////////////
816
817 cases.add_2("Forward-declared enum",
812 cases.add("Forward-declared enum",
818813 \\extern enum enum_ty my_enum;
819814 \\enum enum_ty { FOO };
820815 , &[_][]const u8{
......@@ -825,7 +820,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
825820 \\pub extern var my_enum: enum_enum_ty;
826821 });
827822
828 cases.add_2("Parameterless function pointers",
823 cases.add("Parameterless function pointers",
829824 \\typedef void (*fn0)();
830825 \\typedef void (*fn1)(char);
831826 , &[_][]const u8{
......@@ -833,7 +828,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
833828 \\pub const fn1 = ?extern fn (u8) void;
834829 });
835830
836 cases.add_2("Parameterless function prototypes",
831 cases.add("Parameterless function prototypes",
837832 \\void a() {}
838833 \\void b(void) {}
839834 \\void c();
......@@ -845,7 +840,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
845840 \\pub extern fn d() void;
846841 });
847842
848 cases.add_2("variable declarations",
843 cases.add("variable declarations",
849844 \\extern char arr0[] = "hello";
850845 \\static char arr1[] = "hello";
851846 \\char arr2[] = "hello";
......@@ -855,7 +850,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
855850 \\pub export var arr2: [*c]u8 = "hello";
856851 });
857852
858 cases.add_2("array initializer expr",
853 cases.add("array initializer expr",
859854 \\static void foo(void){
860855 \\ char arr[10] ={1};
861856 \\ char *arr1[10] ={0};
......@@ -863,7 +858,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
863858 , &[_][]const u8{
864859 \\pub fn foo() void {
865860 \\ var arr: [10]u8 = .{
866 \\ @as(u8, 1),
861 \\ @bitCast(u8, @truncate(i8, @as(c_int, 1))),
867862 \\ } ++ .{0} ** 9;
868863 \\ var arr1: [10][*c]u8 = .{
869864 \\ null,
......@@ -871,7 +866,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
871866 \\}
872867 });
873868
874 cases.add_2("enums",
869 cases.add("enums",
875870 \\typedef enum {
876871 \\ a,
877872 \\ b,
......@@ -938,61 +933,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
938933 \\pub const Baz = struct_Baz;
939934 });
940935
941 cases.add_2("#define a char literal",
936 cases.add("#define a char literal",
942937 \\#define A_CHAR 'a'
943938 , &[_][]const u8{
944939 \\pub const A_CHAR = 'a';
945940 });
946941
947 cases.add_2("comment after integer literal",
942 cases.add("comment after integer literal",
948943 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
949944 , &[_][]const u8{
950945 \\pub const SDL_INIT_VIDEO = 0x00000020;
951946 });
952947
953 cases.add_2("u integer suffix after hex literal",
948 cases.add("u integer suffix after hex literal",
954949 \\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
955950 , &[_][]const u8{
956951 \\pub const SDL_INIT_VIDEO = @as(c_uint, 0x00000020);
957952 });
958953
959 cases.add_2("l integer suffix after hex literal",
954 cases.add("l integer suffix after hex literal",
960955 \\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
961956 , &[_][]const u8{
962957 \\pub const SDL_INIT_VIDEO = @as(c_long, 0x00000020);
963958 });
964959
965 cases.add_2("ul integer suffix after hex literal",
960 cases.add("ul integer suffix after hex literal",
966961 \\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
967962 , &[_][]const u8{
968963 \\pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020);
969964 });
970965
971 cases.add_2("lu integer suffix after hex literal",
966 cases.add("lu integer suffix after hex literal",
972967 \\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
973968 , &[_][]const u8{
974969 \\pub const SDL_INIT_VIDEO = @as(c_ulong, 0x00000020);
975970 });
976971
977 cases.add_2("ll integer suffix after hex literal",
972 cases.add("ll integer suffix after hex literal",
978973 \\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
979974 , &[_][]const u8{
980975 \\pub const SDL_INIT_VIDEO = @as(c_longlong, 0x00000020);
981976 });
982977
983 cases.add_2("ull integer suffix after hex literal",
978 cases.add("ull integer suffix after hex literal",
984979 \\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
985980 , &[_][]const u8{
986981 \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020);
987982 });
988983
989 cases.add_2("llu integer suffix after hex literal",
984 cases.add("llu integer suffix after hex literal",
990985 \\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
991986 , &[_][]const u8{
992987 \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 0x00000020);
993988 });
994989
995 cases.add_2("generate inline func for #define global extern fn",
990 cases.add("generate inline func for #define global extern fn",
996991 \\extern void (*fn_ptr)(void);
997992 \\#define foo fn_ptr
998993 \\
......@@ -1012,7 +1007,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10121007 \\}
10131008 });
10141009
1015 cases.add_2("macros with field targets",
1010 cases.add("macros with field targets",
10161011 \\typedef unsigned int GLbitfield;
10171012 \\typedef void (*PFNGLCLEARPROC) (GLbitfield mask);
10181013 \\typedef void(*OpenGLProc)(void);
......@@ -1047,13 +1042,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10471042 \\pub const OpenGLProcs = union_OpenGLProcs;
10481043 });
10491044
1050 cases.add_2("macro pointer cast",
1045 cases.add("macro pointer cast",
10511046 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
10521047 , &[_][]const u8{
10531048 \\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);
10541049 });
10551050
1056 cases.add_2("basic macro function",
1051 cases.add("basic macro function",
10571052 \\extern int c;
10581053 \\#define BASIC(c) (c*2)
10591054 , &[_][]const u8{
......@@ -1064,7 +1059,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10641059 \\}
10651060 });
10661061
1067 cases.add_2("macro defines string literal with hex",
1062 cases.add("macro defines string literal with hex",
10681063 \\#define FOO "aoeu\xab derp"
10691064 \\#define FOO2 "aoeu\x0007a derp"
10701065 \\#define FOO_CHAR '\xfF'
......@@ -1076,7 +1071,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10761071 \\pub const FOO_CHAR = '\xff';
10771072 });
10781073
1079 cases.add_2("variable aliasing",
1074 cases.add("macro add",
1075 \\#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */
1076 \\#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL)
1077 \\#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL)
1078 , &[_][]const u8{
1079 \\pub const PERIPH_BASE = @as(c_ulong, 0x40000000);
1080 ,
1081 \\pub const D3_APB1PERIPH_BASE = PERIPH_BASE + @as(c_ulong, 0x18000000);
1082 ,
1083 \\pub const RCC_BASE = D3_AHB1PERIPH_BASE + @as(c_ulong, 0x4400);
1084 });
1085
1086 cases.add("variable aliasing",
10801087 \\static long a = 2;
10811088 \\static long b = 2;
10821089 \\static int c = 4;
......@@ -1090,81 +1097,55 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10901097 \\ unsigned d = 440;
10911098 \\}
10921099 , &[_][]const u8{
1093 \\pub var a: c_long = @as(c_long, 2);
1094 \\pub var b: c_long = @as(c_long, 2);
1100 \\pub var a: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
1101 \\pub var b: c_long = @bitCast(c_long, @as(c_long, @as(c_int, 2)));
10951102 \\pub var c: c_int = 4;
1096 \\pub export fn foo(_arg_c_1: u8) void {
1097 \\ var c_1 = _arg_c_1;
1103 \\pub export fn foo(arg_c_1: u8) void {
1104 \\ var c_1 = arg_c_1;
10981105 \\ var a_2: c_int = undefined;
1099 \\ var b_3: u8 = @as(u8, 123);
1100 \\ b_3 = @as(u8, a_2);
1106 \\ var b_3: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 123)));
1107 \\ b_3 = @bitCast(u8, @truncate(i8, a_2));
11011108 \\ {
11021109 \\ var d: c_int = 5;
11031110 \\ }
1104 \\ var d: c_uint = @as(c_uint, 440);
1111 \\ var d: c_uint = @bitCast(c_uint, @as(c_int, 440));
11051112 \\}
11061113 });
11071114
1108 cases.add_2("comma operator",
1109 \\int foo(char c) {
1115 cases.add("comma operator",
1116 \\int foo() {
11101117 \\ 2, 4;
11111118 \\ return 2, 4, 6;
11121119 \\}
11131120 , &[_][]const u8{
1114 \\pub export fn foo(_arg_c: u8) c_int {
1115 \\ var c = _arg_c;
1116 \\ _ = 2;
1117 \\ _ = 4;
1118 \\ _ = 2;
1119 \\ _ = 4;
1120 \\ return 6;
1121 \\pub export fn foo() c_int {
1122 \\ _ = @as(c_int, 2);
1123 \\ _ = @as(c_int, 4);
1124 \\ _ = @as(c_int, 2);
1125 \\ _ = @as(c_int, 4);
1126 \\ return @as(c_int, 6);
11211127 \\}
11221128 });
11231129
1124 cases.add_2("wors-case assign",
1125 \\int foo(char c) {
1130 cases.add("worst-case assign",
1131 \\int foo() {
11261132 \\ int a;
11271133 \\ int b;
11281134 \\ a = b = 2;
11291135 \\}
11301136 , &[_][]const u8{
1131 \\pub export fn foo(_arg_c: u8) c_int {
1132 \\ var c = _arg_c;
1137 \\pub export fn foo() c_int {
11331138 \\ var a: c_int = undefined;
11341139 \\ var b: c_int = undefined;
11351140 \\ a = blk: {
1136 \\ const _tmp_1 = 2;
1137 \\ b = _tmp_1;
1138 \\ break :blk _tmp_1;
1141 \\ const tmp = @as(c_int, 2);
1142 \\ b = tmp;
1143 \\ break :blk tmp;
11391144 \\ };
11401145 \\}
11411146 });
11421147
1143 cases.add_2("if statements",
1144 \\int foo(char c) {
1145 \\ if (2) {
1146 \\ int a = 2;
1147 \\ }
1148 \\ if (2, 5) {
1149 \\ int a = 2;
1150 \\ }
1151 \\}
1152 , &[_][]const u8{
1153 \\pub export fn foo(_arg_c: u8) c_int {
1154 \\ var c = _arg_c;
1155 \\ if (2 != 0) {
1156 \\ var a: c_int = 2;
1157 \\ }
1158 \\ if ((blk: {
1159 \\ _ = 2;
1160 \\ break :blk 5;
1161 \\ }) != 0) {
1162 \\ var a: c_int = 2;
1163 \\ }
1164 \\}
1165 });
1166
1167 cases.add_2("while loops",
1148 cases.add("while loops",
11681149 \\int foo() {
11691150 \\ int a = 5;
11701151 \\ while (2)
......@@ -1185,26 +1166,26 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11851166 , &[_][]const u8{
11861167 \\pub export fn foo() c_int {
11871168 \\ var a: c_int = 5;
1188 \\ while (2 != 0) a = 2;
1189 \\ while (4 != 0) {
1190 \\ var a: c_int = 4;
1191 \\ a = 9;
1192 \\ _ = 6;
1193 \\ return a;
1169 \\ while (@as(c_int, 2) != 0) a = 2;
1170 \\ while (@as(c_int, 4) != 0) {
1171 \\ var a_1: c_int = 4;
1172 \\ a_1 = 9;
1173 \\ _ = @as(c_int, 6);
1174 \\ return a_1;
11941175 \\ }
11951176 \\ while (true) {
1196 \\ var a: c_int = 2;
1197 \\ a = 12;
1198 \\ if (!(4 != 0)) break;
1177 \\ var a_1: c_int = 2;
1178 \\ a_1 = 12;
1179 \\ if (!(@as(c_int, 4) != 0)) break;
11991180 \\ }
12001181 \\ while (true) {
12011182 \\ a = 7;
1202 \\ if (!(4 != 0)) break;
1183 \\ if (!(@as(c_int, 4) != 0)) break;
12031184 \\ }
12041185 \\}
12051186 });
12061187
1207 cases.add_2("for loops",
1188 cases.add("for loops",
12081189 \\int foo() {
12091190 \\ for (int i = 2, b = 4; i + 2; i = 2) {
12101191 \\ int a = 2;
......@@ -1217,24 +1198,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12171198 \\ {
12181199 \\ var i: c_int = 2;
12191200 \\ var b: c_int = 4;
1220 \\ while ((i + 2) != 0) : (i = 2) {
1201 \\ while ((i + @as(c_int, 2)) != 0) : (i = 2) {
12211202 \\ var a: c_int = 2;
12221203 \\ a = 6;
1223 \\ _ = 5;
1224 \\ _ = 7;
1204 \\ _ = @as(c_int, 5);
1205 \\ _ = @as(c_int, 7);
12251206 \\ }
12261207 \\ }
1227 \\ var i: u8 = @as(u8, 2);
1208 \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2)));
12281209 \\}
12291210 });
12301211
1231 cases.add_2("shadowing primitive types",
1212 cases.add("shadowing primitive types",
12321213 \\unsigned anyerror = 2;
12331214 , &[_][]const u8{
1234 \\pub export var _anyerror: c_uint = @as(c_uint, 2);
1215 \\pub export var _anyerror: c_uint = @bitCast(c_uint, @as(c_int, 2));
12351216 });
12361217
1237 cases.add_2("floats",
1218 cases.add("floats",
12381219 \\float a = 3.1415;
12391220 \\double b = 3.1415;
12401221 \\int c = 3.1415;
......@@ -1243,22 +1224,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12431224 \\pub export var a: f32 = @floatCast(f32, 3.1415);
12441225 \\pub export var b: f64 = 3.1415;
12451226 \\pub export var c: c_int = @floatToInt(c_int, 3.1415);
1246 \\pub export var d: f64 = @intToFloat(f64, 3);
1227 \\pub export var d: f64 = @intToFloat(f64, @as(c_int, 3));
12471228 });
12481229
1249 cases.add_2("conditional operator",
1230 cases.add("conditional operator",
12501231 \\int bar(void) {
12511232 \\ if (2 ? 5 : 5 ? 4 : 6) 2;
12521233 \\ return 2 ? 5 : 5 ? 4 : 6;
12531234 \\}
12541235 , &[_][]const u8{
12551236 \\pub export fn bar() c_int {
1256 \\ if ((if (2 != 0) 5 else (if (5 != 0) 4 else 6)) != 0) _ = 2;
1257 \\ return if (2 != 0) 5 else if (5 != 0) 4 else 6;
1237 \\ if ((if (@as(c_int, 2) != 0) @as(c_int, 5) else (if (@as(c_int, 5) != 0) @as(c_int, 4) else @as(c_int, 6))) != 0) _ = @as(c_int, 2);
1238 \\ return if (@as(c_int, 2) != 0) @as(c_int, 5) else if (@as(c_int, 5) != 0) @as(c_int, 4) else @as(c_int, 6);
12581239 \\}
12591240 });
12601241
1261 cases.add_2("switch on int",
1242 cases.add("switch on int",
12621243 \\int switch_fn(int i) {
12631244 \\ int res = 0;
12641245 \\ switch (i) {
......@@ -1274,8 +1255,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12741255 \\ }
12751256 \\}
12761257 , &[_][]const u8{
1277 \\pub export fn switch_fn(_arg_i: c_int) c_int {
1278 \\ var i = _arg_i;
1258 \\pub export fn switch_fn(arg_i: c_int) c_int {
1259 \\ var i = arg_i;
12791260 \\ var res: c_int = 0;
12801261 \\ __switch: {
12811262 \\ __case_2: {
......@@ -1293,7 +1274,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12931274 \\ }
12941275 \\ res = 2;
12951276 \\ }
1296 \\ res = (3 * i);
1277 \\ res = (@as(c_int, 3) * i);
12971278 \\ break :__switch;
12981279 \\ }
12991280 \\ res = 5;
......@@ -1301,7 +1282,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13011282 \\}
13021283 });
13031284
1304 cases.add_2("type referenced struct",
1285 cases.add("type referenced struct",
13051286 \\struct Foo {
13061287 \\ struct Bar{
13071288 \\ int b;
......@@ -1317,52 +1298,52 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13171298 \\};
13181299 });
13191300
1320 cases.add_2("undefined array global",
1301 cases.add("undefined array global",
13211302 \\int array[100] = {};
13221303 , &[_][]const u8{
13231304 \\pub export var array: [100]c_int = .{0} ** 100;
13241305 });
13251306
1326 cases.add_2("restrict -> noalias",
1307 cases.add("restrict -> noalias",
13271308 \\void foo(void *restrict bar, void *restrict);
13281309 , &[_][]const u8{
13291310 \\pub extern fn foo(noalias bar: ?*c_void, noalias ?*c_void) void;
13301311 });
13311312
1332 cases.add_2("assign",
1313 cases.add("assign",
13331314 \\int max(int a) {
13341315 \\ int tmp;
13351316 \\ tmp = a;
13361317 \\ a = tmp;
13371318 \\}
13381319 , &[_][]const u8{
1339 \\pub export fn max(_arg_a: c_int) c_int {
1340 \\ var a = _arg_a;
1320 \\pub export fn max(arg_a: c_int) c_int {
1321 \\ var a = arg_a;
13411322 \\ var tmp: c_int = undefined;
13421323 \\ tmp = a;
13431324 \\ a = tmp;
13441325 \\}
13451326 });
13461327
1347 cases.add_2("chaining assign",
1328 cases.add("chaining assign",
13481329 \\void max(int a) {
13491330 \\ int b, c;
13501331 \\ c = b = a;
13511332 \\}
13521333 , &[_][]const u8{
1353 \\pub export fn max(_arg_a: c_int) void {
1354 \\ var a = _arg_a;
1334 \\pub export fn max(arg_a: c_int) void {
1335 \\ var a = arg_a;
13551336 \\ var b: c_int = undefined;
13561337 \\ var c: c_int = undefined;
13571338 \\ c = blk: {
1358 \\ const _tmp_1 = a;
1359 \\ b = _tmp_1;
1360 \\ break :blk _tmp_1;
1339 \\ const tmp = a;
1340 \\ b = tmp;
1341 \\ break :blk tmp;
13611342 \\ };
13621343 \\}
13631344 });
13641345
1365 cases.add_2("anonymous enum",
1346 cases.add("anonymous enum",
13661347 \\enum {
13671348 \\ One,
13681349 \\ Two,
......@@ -1376,18 +1357,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13761357 \\};
13771358 });
13781359
1379 cases.add_2("c style cast",
1360 cases.add("c style cast",
13801361 \\int float_to_int(float a) {
13811362 \\ return (int)a;
13821363 \\}
13831364 , &[_][]const u8{
1384 \\pub export fn float_to_int(_arg_a: f32) c_int {
1385 \\ var a = _arg_a;
1365 \\pub export fn float_to_int(arg_a: f32) c_int {
1366 \\ var a = arg_a;
13861367 \\ return @floatToInt(c_int, a);
13871368 \\}
13881369 });
13891370
1390 cases.add_2("escape sequences",
1371 // TODO translate-c should in theory be able to figure out to drop all these casts
1372 cases.add("escape sequences",
13911373 \\const char *escapes() {
13921374 \\char a = '\'',
13931375 \\ b = '\\',
......@@ -1405,22 +1387,22 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14051387 \\
14061388 , &[_][]const u8{
14071389 \\pub export fn escapes() [*c]const u8 {
1408 \\ var a: u8 = @as(u8, '\'');
1409 \\ var b: u8 = @as(u8, '\\');
1410 \\ var c: u8 = @as(u8, '\x07');
1411 \\ var d: u8 = @as(u8, '\x08');
1412 \\ var e: u8 = @as(u8, '\x0c');
1413 \\ var f: u8 = @as(u8, '\n');
1414 \\ var g: u8 = @as(u8, '\r');
1415 \\ var h: u8 = @as(u8, '\t');
1416 \\ var i: u8 = @as(u8, '\x0b');
1417 \\ var j: u8 = @as(u8, '\x00');
1418 \\ var k: u8 = @as(u8, '\"');
1390 \\ var a: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\'')));
1391 \\ var b: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\\')));
1392 \\ var c: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x07')));
1393 \\ var d: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x08')));
1394 \\ var e: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0c')));
1395 \\ var f: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\n')));
1396 \\ var g: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\r')));
1397 \\ var h: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\t')));
1398 \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x0b')));
1399 \\ var j: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\x00')));
1400 \\ var k: u8 = @bitCast(u8, @truncate(i8, @as(c_int, '\"')));
14191401 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
14201402 \\}
14211403 });
14221404
1423 cases.add_2("do loop",
1405 cases.add("do loop",
14241406 \\void foo(void) {
14251407 \\ int a = 2;
14261408 \\ do {
......@@ -1436,18 +1418,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14361418 \\pub export fn foo() void {
14371419 \\ var a: c_int = 2;
14381420 \\ while (true) {
1439 \\ a = (a - 1);
1421 \\ a = (a - @as(c_int, 1));
14401422 \\ if (!(a != 0)) break;
14411423 \\ }
14421424 \\ var b: c_int = 2;
14431425 \\ while (true) {
1444 \\ b = (b - 1);
1426 \\ b = (b - @as(c_int, 1));
14451427 \\ if (!(b != 0)) break;
14461428 \\ }
14471429 \\}
14481430 });
14491431
1450 cases.add_2("logical and, logical or, on non-bool values, extra parens",
1432 cases.add("logical and, logical or, on non-bool values, extra parens",
14511433 \\enum Foo {
14521434 \\ FooA,
14531435 \\ FooB,
......@@ -1477,10 +1459,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14771459 \\ C,
14781460 \\};
14791461 \\pub const SomeTypedef = c_int;
1480 \\pub export fn and_or_non_bool(_arg_a: c_int, _arg_b: f32, _arg_c: ?*c_void) c_int {
1481 \\ var a = _arg_a;
1482 \\ var b = _arg_b;
1483 \\ var c = _arg_c;
1462 \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
1463 \\ var a = arg_a;
1464 \\ var b = arg_b;
1465 \\ var c = arg_c;
14841466 \\ var d: enum_Foo = @intToEnum(enum_Foo, FooA);
14851467 \\ var e: c_int = @boolToInt(((a != 0) and (b != 0)));
14861468 \\ var f: c_int = @boolToInt(((b != 0) and (c != null)));
......@@ -1500,7 +1482,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15001482 \\pub const Foo = enum_Foo;
15011483 });
15021484
1503 cases.add_2("qualified struct and enum",
1485 cases.add("qualified struct and enum",
15041486 \\struct Foo {
15051487 \\ int x;
15061488 \\ int y;
......@@ -1526,19 +1508,19 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15261508 \\pub const Bar = enum_Bar;
15271509 });
15281510
1529 cases.add_2("bitwise binary operators, simpler parens",
1511 cases.add("bitwise binary operators, simpler parens",
15301512 \\int max(int a, int b) {
15311513 \\ return (a & b) ^ (a | b);
15321514 \\}
15331515 , &[_][]const u8{
1534 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1535 \\ var a = _arg_a;
1536 \\ var b = _arg_b;
1516 \\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
1517 \\ var a = arg_a;
1518 \\ var b = arg_b;
15371519 \\ return ((a & b) ^ (a | b));
15381520 \\}
15391521 });
15401522
1541 cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
1523 cases.add("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
15421524 \\int test_comparisons(int a, int b) {
15431525 \\ int c = (a < b);
15441526 \\ int d = (a > b);
......@@ -1550,9 +1532,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15501532 \\ return i;
15511533 \\}
15521534 , &[_][]const u8{
1553 \\pub export fn test_comparisons(_arg_a: c_int, _arg_b: c_int) c_int {
1554 \\ var a = _arg_a;
1555 \\ var b = _arg_b;
1535 \\pub export fn test_comparisons(arg_a: c_int, arg_b: c_int) c_int {
1536 \\ var a = arg_a;
1537 \\ var b = arg_b;
15561538 \\ var c: c_int = @boolToInt((a < b));
15571539 \\ var d: c_int = @boolToInt((a > b));
15581540 \\ var e: c_int = @boolToInt((a <= b));
......@@ -1564,7 +1546,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15641546 \\}
15651547 });
15661548
1567 cases.add_2("==, !=",
1549 cases.add("==, !=",
15681550 \\int max(int a, int b) {
15691551 \\ if (a == b)
15701552 \\ return a;
......@@ -1573,16 +1555,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15731555 \\ return a;
15741556 \\}
15751557 , &[_][]const u8{
1576 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1577 \\ var a = _arg_a;
1578 \\ var b = _arg_b;
1558 \\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
1559 \\ var a = arg_a;
1560 \\ var b = arg_b;
15791561 \\ if (a == b) return a;
15801562 \\ if (a != b) return b;
15811563 \\ return a;
15821564 \\}
15831565 });
15841566
1585 cases.add_2("typedeffed bool expression",
1567 cases.add("typedeffed bool expression",
15861568 \\typedef char* yes;
15871569 \\void foo(void) {
15881570 \\ yes a;
......@@ -1592,11 +1574,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15921574 \\pub const yes = [*c]u8;
15931575 \\pub export fn foo() void {
15941576 \\ var a: yes = undefined;
1595 \\ if (a != null) _ = 2;
1577 \\ if (a != null) _ = @as(c_int, 2);
15961578 \\}
15971579 });
15981580
1599 cases.add_2("statement expression",
1581 cases.add("statement expression",
16001582 \\int foo(void) {
16011583 \\ return ({
16021584 \\ int a = 1;
......@@ -1614,7 +1596,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16141596 \\}
16151597 });
16161598
1617 cases.add_2("field access expression",
1599 cases.add("field access expression",
16181600 \\#define ARROW a->b
16191601 \\#define DOT a.b
16201602 \\extern struct Foo {
......@@ -1643,7 +1625,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16431625 \\pub const ARROW = a.*.b;
16441626 });
16451627
1646 cases.add_2("array access",
1628 cases.add("array access",
16471629 \\#define ACCESS array[2]
16481630 \\int array[100] = {};
16491631 \\int foo(int index) {
......@@ -1651,15 +1633,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16511633 \\}
16521634 , &[_][]const u8{
16531635 \\pub export var array: [100]c_int = .{0} ** 100;
1654 \\pub export fn foo(_arg_index: c_int) c_int {
1655 \\ var index = _arg_index;
1636 \\pub export fn foo(arg_index: c_int) c_int {
1637 \\ var index = arg_index;
16561638 \\ return array[index];
16571639 \\}
16581640 ,
16591641 \\pub const ACCESS = array[2];
16601642 });
16611643
1662 cases.add_2("macro call",
1644 cases.add("macro call",
16631645 \\#define CALL(arg) bar(arg)
16641646 , &[_][]const u8{
16651647 \\pub inline fn CALL(arg: var) @TypeOf(bar(arg)) {
......@@ -1667,7 +1649,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16671649 \\}
16681650 });
16691651
1670 cases.add_2("logical and, logical or",
1652 cases.add("logical and, logical or",
16711653 \\int max(int a, int b) {
16721654 \\ if (a < b || a == b)
16731655 \\ return b;
......@@ -1676,16 +1658,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16761658 \\ return a;
16771659 \\}
16781660 , &[_][]const u8{
1679 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1680 \\ var a = _arg_a;
1681 \\ var b = _arg_b;
1661 \\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
1662 \\ var a = arg_a;
1663 \\ var b = arg_b;
16821664 \\ if ((a < b) or (a == b)) return b;
16831665 \\ if ((a >= b) and (a == b)) return a;
16841666 \\ return a;
16851667 \\}
16861668 });
16871669
1688 cases.add_2("if statement",
1670 cases.add("simple if statement",
16891671 \\int max(int a, int b) {
16901672 \\ if (a < b)
16911673 \\ return b;
......@@ -1698,16 +1680,39 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16981680 \\ if (a < b) ; else ;
16991681 \\}
17001682 , &[_][]const u8{
1701 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1702 \\ var a = _arg_a;
1703 \\ var b = _arg_b;
1683 \\pub export fn max(arg_a: c_int, arg_b: c_int) c_int {
1684 \\ var a = arg_a;
1685 \\ var b = arg_b;
17041686 \\ if (a < b) return b;
17051687 \\ if (a < b) return b else return a;
17061688 \\ if (a < b) {} else {}
17071689 \\}
17081690 });
17091691
1710 cases.add_2("if on non-bool",
1692 cases.add("if statements",
1693 \\int foo() {
1694 \\ if (2) {
1695 \\ int a = 2;
1696 \\ }
1697 \\ if (2, 5) {
1698 \\ int a = 2;
1699 \\ }
1700 \\}
1701 , &[_][]const u8{
1702 \\pub export fn foo() c_int {
1703 \\ if (@as(c_int, 2) != 0) {
1704 \\ var a: c_int = 2;
1705 \\ }
1706 \\ if ((blk: {
1707 \\ _ = @as(c_int, 2);
1708 \\ break :blk @as(c_int, 5);
1709 \\ }) != 0) {
1710 \\ var a: c_int = 2;
1711 \\ }
1712 \\}
1713 });
1714
1715 cases.add("if on non-bool",
17111716 \\enum SomeEnum { A, B, C };
17121717 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
17131718 \\ if (a) return 0;
......@@ -1722,11 +1727,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17221727 \\ B,
17231728 \\ C,
17241729 \\};
1725 \\pub export fn if_none_bool(_arg_a: c_int, _arg_b: f32, _arg_c: ?*c_void, _arg_d: enum_SomeEnum) c_int {
1726 \\ var a = _arg_a;
1727 \\ var b = _arg_b;
1728 \\ var c = _arg_c;
1729 \\ var d = _arg_d;
1730 \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
1731 \\ var a = arg_a;
1732 \\ var b = arg_b;
1733 \\ var c = arg_c;
1734 \\ var d = arg_d;
17301735 \\ if (a != 0) return 0;
17311736 \\ if (b != 0) return 1;
17321737 \\ if (c != null) return 2;
......@@ -1735,7 +1740,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17351740 \\}
17361741 });
17371742
1738 cases.add_2("simple data types",
1743 cases.add("simple data types",
17391744 \\#include <stdint.h>
17401745 \\int foo(char a, unsigned char b, signed char c);
17411746 \\int foo(char a, unsigned char b, signed char c); // test a duplicate prototype
......@@ -1747,18 +1752,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17471752 \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void;
17481753 });
17491754
1750 cases.add_2("simple function",
1755 cases.add("simple function",
17511756 \\int abs(int a) {
17521757 \\ return a < 0 ? -a : a;
17531758 \\}
17541759 , &[_][]const u8{
1755 \\pub export fn abs(_arg_a: c_int) c_int {
1756 \\ var a = _arg_a;
1757 \\ return if (a < 0) -a else a;
1760 \\pub export fn abs(arg_a: c_int) c_int {
1761 \\ var a = arg_a;
1762 \\ return if (a < @as(c_int, 0)) -a else a;
17581763 \\}
17591764 });
17601765
1761 cases.add_2("post increment",
1766 cases.add("post increment",
17621767 \\unsigned foo1(unsigned a) {
17631768 \\ a++;
17641769 \\ return a;
......@@ -1767,20 +1772,29 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17671772 \\ a++;
17681773 \\ return a;
17691774 \\}
1775 \\int *foo3(int *a) {
1776 \\ a++;
1777 \\ return a;
1778 \\}
17701779 , &[_][]const u8{
1771 \\pub export fn foo1(_arg_a: c_uint) c_uint {
1772 \\ var a = _arg_a;
1780 \\pub export fn foo1(arg_a: c_uint) c_uint {
1781 \\ var a = arg_a;
17731782 \\ a +%= 1;
17741783 \\ return a;
17751784 \\}
1776 \\pub export fn foo2(_arg_a: c_int) c_int {
1777 \\ var a = _arg_a;
1785 \\pub export fn foo2(arg_a: c_int) c_int {
1786 \\ var a = arg_a;
1787 \\ a += 1;
1788 \\ return a;
1789 \\}
1790 \\pub export fn foo3(arg_a: [*c]c_int) [*c]c_int {
1791 \\ var a = arg_a;
17781792 \\ a += 1;
17791793 \\ return a;
17801794 \\}
17811795 });
17821796
1783 cases.add_2("deref function pointer",
1797 cases.add("deref function pointer",
17841798 \\void foo(void) {}
17851799 \\int baz(void) { return 0; }
17861800 \\void bar(void) {
......@@ -1810,7 +1824,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18101824 \\}
18111825 });
18121826
1813 cases.add_2("pre increment/decrement",
1827 cases.add("pre increment/decrement",
18141828 \\void foo(void) {
18151829 \\ int i = 0;
18161830 \\ unsigned u = 0;
......@@ -1826,35 +1840,35 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18261840 , &[_][]const u8{
18271841 \\pub export fn foo() void {
18281842 \\ var i: c_int = 0;
1829 \\ var u: c_uint = @as(c_uint, 0);
1843 \\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
18301844 \\ i += 1;
18311845 \\ i -= 1;
18321846 \\ u +%= 1;
18331847 \\ u -%= 1;
18341848 \\ i = (blk: {
1835 \\ const _ref_1 = &i;
1836 \\ _ref_1.* += 1;
1837 \\ break :blk _ref_1.*;
1849 \\ const ref = &i;
1850 \\ ref.* += 1;
1851 \\ break :blk ref.*;
18381852 \\ });
18391853 \\ i = (blk: {
1840 \\ const _ref_2 = &i;
1841 \\ _ref_2.* -= 1;
1842 \\ break :blk _ref_2.*;
1854 \\ const ref = &i;
1855 \\ ref.* -= 1;
1856 \\ break :blk ref.*;
18431857 \\ });
18441858 \\ u = (blk: {
1845 \\ const _ref_3 = &u;
1846 \\ _ref_3.* +%= 1;
1847 \\ break :blk _ref_3.*;
1859 \\ const ref = &u;
1860 \\ ref.* +%= 1;
1861 \\ break :blk ref.*;
18481862 \\ });
18491863 \\ u = (blk: {
1850 \\ const _ref_4 = &u;
1851 \\ _ref_4.* -%= 1;
1852 \\ break :blk _ref_4.*;
1864 \\ const ref = &u;
1865 \\ ref.* -%= 1;
1866 \\ break :blk ref.*;
18531867 \\ });
18541868 \\}
18551869 });
18561870
1857 cases.add_2("shift right assign",
1871 cases.add("shift right assign",
18581872 \\int log2(unsigned a) {
18591873 \\ int i = 0;
18601874 \\ while (a > 0) {
......@@ -1863,17 +1877,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18631877 \\ return i;
18641878 \\}
18651879 , &[_][]const u8{
1866 \\pub export fn log2(_arg_a: c_uint) c_int {
1867 \\ var a = _arg_a;
1880 \\pub export fn log2(arg_a: c_uint) c_int {
1881 \\ var a = arg_a;
18681882 \\ var i: c_int = 0;
1869 \\ while (a > @as(c_uint, 0)) {
1883 \\ while (a > @bitCast(c_uint, @as(c_int, 0))) {
18701884 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
18711885 \\ }
18721886 \\ return i;
18731887 \\}
18741888 });
18751889
1876 cases.add_2("shift right assign with a fixed size type",
1890 cases.add("shift right assign with a fixed size type",
18771891 \\#include <stdint.h>
18781892 \\int log2(uint32_t a) {
18791893 \\ int i = 0;
......@@ -1883,17 +1897,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18831897 \\ return i;
18841898 \\}
18851899 , &[_][]const u8{
1886 \\pub export fn log2(_arg_a: u32) c_int {
1887 \\ var a = _arg_a;
1900 \\pub export fn log2(arg_a: u32) c_int {
1901 \\ var a = arg_a;
18881902 \\ var i: c_int = 0;
1889 \\ while (a > @as(c_uint, 0)) {
1903 \\ while (a > @bitCast(c_uint, @as(c_int, 0))) {
18901904 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
18911905 \\ }
18921906 \\ return i;
18931907 \\}
18941908 });
18951909
1896 cases.add_2("compound assignment operators",
1910 cases.add("compound assignment operators",
18971911 \\void foo(void) {
18981912 \\ int a = 0;
18991913 \\ a += (a += 1);
......@@ -1909,49 +1923,49 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
19091923 \\pub export fn foo() void {
19101924 \\ var a: c_int = 0;
19111925 \\ a += (blk: {
1912 \\ const _ref_1 = &a;
1913 \\ _ref_1.* = _ref_1.* + 1;
1914 \\ break :blk _ref_1.*;
1926 \\ const ref = &a;
1927 \\ ref.* = ref.* + @as(c_int, 1);
1928 \\ break :blk ref.*;
19151929 \\ });
19161930 \\ a -= (blk: {
1917 \\ const _ref_2 = &a;
1918 \\ _ref_2.* = _ref_2.* - 1;
1919 \\ break :blk _ref_2.*;
1931 \\ const ref = &a;
1932 \\ ref.* = ref.* - @as(c_int, 1);
1933 \\ break :blk ref.*;
19201934 \\ });
19211935 \\ a *= (blk: {
1922 \\ const _ref_3 = &a;
1923 \\ _ref_3.* = _ref_3.* * 1;
1924 \\ break :blk _ref_3.*;
1936 \\ const ref = &a;
1937 \\ ref.* = ref.* * @as(c_int, 1);
1938 \\ break :blk ref.*;
19251939 \\ });
19261940 \\ a &= (blk: {
1927 \\ const _ref_4 = &a;
1928 \\ _ref_4.* = _ref_4.* & 1;
1929 \\ break :blk _ref_4.*;
1941 \\ const ref = &a;
1942 \\ ref.* = ref.* & @as(c_int, 1);
1943 \\ break :blk ref.*;
19301944 \\ });
19311945 \\ a |= (blk: {
1932 \\ const _ref_5 = &a;
1933 \\ _ref_5.* = _ref_5.* | 1;
1934 \\ break :blk _ref_5.*;
1946 \\ const ref = &a;
1947 \\ ref.* = ref.* | @as(c_int, 1);
1948 \\ break :blk ref.*;
19351949 \\ });
19361950 \\ a ^= (blk: {
1937 \\ const _ref_6 = &a;
1938 \\ _ref_6.* = _ref_6.* ^ 1;
1939 \\ break :blk _ref_6.*;
1951 \\ const ref = &a;
1952 \\ ref.* = ref.* ^ @as(c_int, 1);
1953 \\ break :blk ref.*;
19401954 \\ });
19411955 \\ a >>= @as(@import("std").math.Log2Int(c_int), (blk: {
1942 \\ const _ref_7 = &a;
1943 \\ _ref_7.* = _ref_7.* >> @as(@import("std").math.Log2Int(c_int), 1);
1944 \\ break :blk _ref_7.*;
1956 \\ const ref = &a;
1957 \\ ref.* = ref.* >> @as(@import("std").math.Log2Int(c_int), @as(c_int, 1));
1958 \\ break :blk ref.*;
19451959 \\ }));
19461960 \\ a <<= @as(@import("std").math.Log2Int(c_int), (blk: {
1947 \\ const _ref_8 = &a;
1948 \\ _ref_8.* = _ref_8.* << @as(@import("std").math.Log2Int(c_int), 1);
1949 \\ break :blk _ref_8.*;
1961 \\ const ref = &a;
1962 \\ ref.* = ref.* << @as(@import("std").math.Log2Int(c_int), @as(c_int, 1));
1963 \\ break :blk ref.*;
19501964 \\ }));
19511965 \\}
19521966 });
19531967
1954 cases.add_2("compound assignment operators unsigned",
1968 cases.add("compound assignment operators unsigned",
19551969 \\void foo(void) {
19561970 \\ unsigned a = 0;
19571971 \\ a += (a += 1);
......@@ -1965,51 +1979,51 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
19651979 \\}
19661980 , &[_][]const u8{
19671981 \\pub export fn foo() void {
1968 \\ var a: c_uint = @as(c_uint, 0);
1982 \\ var a: c_uint = @bitCast(c_uint, @as(c_int, 0));
19691983 \\ a +%= (blk: {
1970 \\ const _ref_1 = &a;
1971 \\ _ref_1.* = _ref_1.* +% @as(c_uint, 1);
1972 \\ break :blk _ref_1.*;
1984 \\ const ref = &a;
1985 \\ ref.* = ref.* +% @bitCast(c_uint, @as(c_int, 1));
1986 \\ break :blk ref.*;
19731987 \\ });
19741988 \\ a -%= (blk: {
1975 \\ const _ref_2 = &a;
1976 \\ _ref_2.* = _ref_2.* -% @as(c_uint, 1);
1977 \\ break :blk _ref_2.*;
1989 \\ const ref = &a;
1990 \\ ref.* = ref.* -% @bitCast(c_uint, @as(c_int, 1));
1991 \\ break :blk ref.*;
19781992 \\ });
19791993 \\ a *%= (blk: {
1980 \\ const _ref_3 = &a;
1981 \\ _ref_3.* = _ref_3.* *% @as(c_uint, 1);
1982 \\ break :blk _ref_3.*;
1994 \\ const ref = &a;
1995 \\ ref.* = ref.* *% @bitCast(c_uint, @as(c_int, 1));
1996 \\ break :blk ref.*;
19831997 \\ });
19841998 \\ a &= (blk: {
1985 \\ const _ref_4 = &a;
1986 \\ _ref_4.* = _ref_4.* & @as(c_uint, 1);
1987 \\ break :blk _ref_4.*;
1999 \\ const ref = &a;
2000 \\ ref.* = ref.* & @bitCast(c_uint, @as(c_int, 1));
2001 \\ break :blk ref.*;
19882002 \\ });
19892003 \\ a |= (blk: {
1990 \\ const _ref_5 = &a;
1991 \\ _ref_5.* = _ref_5.* | @as(c_uint, 1);
1992 \\ break :blk _ref_5.*;
2004 \\ const ref = &a;
2005 \\ ref.* = ref.* | @bitCast(c_uint, @as(c_int, 1));
2006 \\ break :blk ref.*;
19932007 \\ });
19942008 \\ a ^= (blk: {
1995 \\ const _ref_6 = &a;
1996 \\ _ref_6.* = _ref_6.* ^ @as(c_uint, 1);
1997 \\ break :blk _ref_6.*;
2009 \\ const ref = &a;
2010 \\ ref.* = ref.* ^ @bitCast(c_uint, @as(c_int, 1));
2011 \\ break :blk ref.*;
19982012 \\ });
19992013 \\ a >>= @as(@import("std").math.Log2Int(c_uint), (blk: {
2000 \\ const _ref_7 = &a;
2001 \\ _ref_7.* = _ref_7.* >> @as(@import("std").math.Log2Int(c_int), 1);
2002 \\ break :blk _ref_7.*;
2014 \\ const ref = &a;
2015 \\ ref.* = ref.* >> @as(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2016 \\ break :blk ref.*;
20032017 \\ }));
20042018 \\ a <<= @as(@import("std").math.Log2Int(c_uint), (blk: {
2005 \\ const _ref_8 = &a;
2006 \\ _ref_8.* = _ref_8.* << @as(@import("std").math.Log2Int(c_int), 1);
2007 \\ break :blk _ref_8.*;
2019 \\ const ref = &a;
2020 \\ ref.* = ref.* << @as(@import("std").math.Log2Int(c_int), @as(c_int, 1));
2021 \\ break :blk ref.*;
20082022 \\ }));
20092023 \\}
20102024 });
20112025
2012 cases.add_2("post increment/decrement",
2026 cases.add("post increment/decrement",
20132027 \\void foo(void) {
20142028 \\ int i = 0;
20152029 \\ unsigned u = 0;
......@@ -2025,39 +2039,39 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20252039 , &[_][]const u8{
20262040 \\pub export fn foo() void {
20272041 \\ var i: c_int = 0;
2028 \\ var u: c_uint = @as(c_uint, 0);
2042 \\ var u: c_uint = @bitCast(c_uint, @as(c_int, 0));
20292043 \\ i += 1;
20302044 \\ i -= 1;
20312045 \\ u +%= 1;
20322046 \\ u -%= 1;
20332047 \\ i = (blk: {
2034 \\ const _ref_1 = &i;
2035 \\ const _tmp_2 = _ref_1.*;
2036 \\ _ref_1.* += 1;
2037 \\ break :blk _tmp_2;
2048 \\ const ref = &i;
2049 \\ const tmp = ref.*;
2050 \\ ref.* += 1;
2051 \\ break :blk tmp;
20382052 \\ });
20392053 \\ i = (blk: {
2040 \\ const _ref_3 = &i;
2041 \\ const _tmp_4 = _ref_3.*;
2042 \\ _ref_3.* -= 1;
2043 \\ break :blk _tmp_4;
2054 \\ const ref = &i;
2055 \\ const tmp = ref.*;
2056 \\ ref.* -= 1;
2057 \\ break :blk tmp;
20442058 \\ });
20452059 \\ u = (blk: {
2046 \\ const _ref_5 = &u;
2047 \\ const _tmp_6 = _ref_5.*;
2048 \\ _ref_5.* +%= 1;
2049 \\ break :blk _tmp_6;
2060 \\ const ref = &u;
2061 \\ const tmp = ref.*;
2062 \\ ref.* +%= 1;
2063 \\ break :blk tmp;
20502064 \\ });
20512065 \\ u = (blk: {
2052 \\ const _ref_7 = &u;
2053 \\ const _tmp_8 = _ref_7.*;
2054 \\ _ref_7.* -%= 1;
2055 \\ break :blk _tmp_8;
2066 \\ const ref = &u;
2067 \\ const tmp = ref.*;
2068 \\ ref.* -%= 1;
2069 \\ break :blk tmp;
20562070 \\ });
20572071 \\}
20582072 });
20592073
2060 cases.add_2("implicit casts",
2074 cases.add("implicit casts",
20612075 \\#include <stdbool.h>
20622076 \\
20632077 \\void fn_int(int x);
......@@ -2067,7 +2081,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20672081 \\void fn_bool(bool x);
20682082 \\void fn_ptr(void *x);
20692083 \\
2070 \\void call(int q) {
2084 \\void call() {
20712085 \\ fn_int(3.0f);
20722086 \\ fn_int(3.0);
20732087 \\ fn_int(3.0L);
......@@ -2092,28 +2106,27 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
20922106 \\pub extern fn fn_char(x: u8) void;
20932107 \\pub extern fn fn_bool(x: bool) void;
20942108 \\pub extern fn fn_ptr(x: ?*c_void) void;
2095 \\pub export fn call(_arg_q: c_int) void {
2096 \\ var q = _arg_q;
2109 \\pub export fn call() void {
20972110 \\ fn_int(@floatToInt(c_int, 3));
20982111 \\ fn_int(@floatToInt(c_int, 3));
20992112 \\ fn_int(@floatToInt(c_int, 3));
2100 \\ fn_int(1094861636);
2101 \\ fn_f32(@intToFloat(f32, 3));
2102 \\ fn_f64(@intToFloat(f64, 3));
2103 \\ fn_char(@as(u8, '3'));
2104 \\ fn_char(@as(u8, '\x01'));
2105 \\ fn_char(@as(u8, 0));
2113 \\ fn_int(@as(c_int, 1094861636));
2114 \\ fn_f32(@intToFloat(f32, @as(c_int, 3)));
2115 \\ fn_f64(@intToFloat(f64, @as(c_int, 3)));
2116 \\ fn_char(@bitCast(u8, @truncate(i8, @as(c_int, '3'))));
2117 \\ fn_char(@bitCast(u8, @truncate(i8, @as(c_int, '\x01'))));
2118 \\ fn_char(@bitCast(u8, @truncate(i8, @as(c_int, 0))));
21062119 \\ fn_f32(3);
21072120 \\ fn_f64(3);
2108 \\ fn_bool(123 != 0);
2109 \\ fn_bool(0 != 0);
2121 \\ fn_bool(@as(c_int, 123) != 0);
2122 \\ fn_bool(@as(c_int, 0) != 0);
21102123 \\ fn_bool(@ptrToInt(&fn_int) != 0);
21112124 \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
2112 \\ fn_ptr(@intToPtr(?*c_void, 42));
2125 \\ fn_ptr(@intToPtr(?*c_void, @as(c_int, 42)));
21132126 \\}
21142127 });
21152128
2116 cases.add_2("function call",
2129 cases.add("function call",
21172130 \\static void bar(void) { }
21182131 \\void foo(int *(baz)(void)) {
21192132 \\ bar();
......@@ -2121,14 +2134,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21212134 \\}
21222135 , &[_][]const u8{
21232136 \\pub fn bar() void {}
2124 \\pub export fn foo(_arg_baz: ?extern fn () [*c]c_int) void {
2125 \\ var baz = _arg_baz;
2137 \\pub export fn foo(arg_baz: ?extern fn () [*c]c_int) void {
2138 \\ var baz = arg_baz;
21262139 \\ bar();
21272140 \\ _ = baz.?();
21282141 \\}
21292142 });
21302143
2131 cases.add_2("macro defines string literal with octal",
2144 cases.add("macro defines string literal with octal",
21322145 \\#define FOO "aoeu\023 derp"
21332146 \\#define FOO2 "aoeu\0234 derp"
21342147 \\#define FOO_CHAR '\077'
......@@ -2140,7 +2153,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21402153 \\pub const FOO_CHAR = '\x3f';
21412154 });
21422155
2143 cases.add_2("enums",
2156 cases.add("enums",
21442157 \\enum Foo {
21452158 \\ FooA,
21462159 \\ FooB,
......@@ -2162,7 +2175,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21622175 \\pub const Foo = enum_Foo;
21632176 });
21642177
2165 cases.add_2("enums",
2178 cases.add("enums",
21662179 \\enum Foo {
21672180 \\ FooA = 2,
21682181 \\ FooB = 5,
......@@ -2184,7 +2197,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21842197 \\pub const Foo = enum_Foo;
21852198 });
21862199
2187 cases.add_2("macro cast",
2200 cases.add("macro cast",
21882201 \\#define FOO(bar) baz((void *)(baz))
21892202 , &[_][]const u8{
21902203 \\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 +2205,111 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
21922205 \\}
21932206 });
21942207
2195 cases.add_2("macro conditional operator",
2208 cases.add("macro conditional operator",
21962209 \\#define FOO a ? b : c
21972210 , &[_][]const u8{
21982211 \\pub const FOO = if (a) b else c;
21992212 });
22002213
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.?();
2214 cases.add("do while as expr",
2215 \\static void foo(void) {
2216 \\ if (1)
2217 \\ do {} while (0);
22272218 \\}
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 */
22672219 , &[_][]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);
2220 \\pub fn foo() void {
2221 \\ if (@as(c_int, 1) != 0) while (true) {
2222 \\ if (!(@as(c_int, 0) != 0)) break;
2223 \\ };
2224 \\}
22812225 });
22822226
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
2227 cases.add("macro comparisions",
2228 \\#define MIN(a, b) ((b) < (a) ? (b) : (a))
2229 \\#define MAX(a, b) ((b) > (a) ? (b) : (a))
22962230 , &[_][]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);
2231 \\pub inline fn MIN(a: var, b: var) @TypeOf(if (b < a) b else a) {
2232 \\ return if (b < a) b else a;
23162233 \\}
23172234 ,
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);
2235 \\pub inline fn MAX(a: var, b: var) @TypeOf(if (b > a) b else a) {
2236 \\ return if (b > a) b else a;
2237 \\}
23252238 });
23262239
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 \\ }
2240 // TODO: detect to use different block labels here
2241 cases.add("nested assignment",
2242 \\int foo(int *p, int x) {
2243 \\ return *p++ = x;
23412244 \\}
23422245 , &[_][]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 \\ }
2246 \\pub export fn foo(arg_p: [*c]c_int, arg_x: c_int) c_int {
2247 \\ var p = arg_p;
2248 \\ var x = arg_x;
2249 \\ return blk: {
2250 \\ const tmp = x;
2251 \\ (blk: {
2252 \\ const ref = &p;
2253 \\ const tmp_1 = ref.*;
2254 \\ ref.* += 1;
2255 \\ break :blk tmp_1;
2256 \\ }).?.* = tmp;
2257 \\ break :blk tmp;
2258 \\ };
23662259 \\}
23672260 });
23682261
2369 cases.add("for loop with var init but empty body",
2370 \\void foo(void) {
2371 \\ for (int x = 0; x < 10; x++);
2262 cases.add("widening and truncating integer casting to different signedness",
2263 \\unsigned long foo(void) {
2264 \\ return -1;
2265 \\}
2266 \\unsigned short bar(long x) {
2267 \\ return x;
23722268 \\}
23732269 , &[_][]const u8{
2374 \\pub fn foo() void {
2375 \\ {
2376 \\ var x: c_int = 0;
2377 \\ while (x < 10) : (x += 1) {}
2378 \\ }
2270 \\pub export fn foo() c_ulong {
2271 \\ return @bitCast(c_ulong, @as(c_long, -@as(c_int, 1)));
2272 \\}
2273 \\pub export fn bar(arg_x: c_long) c_ushort {
2274 \\ var x = arg_x;
2275 \\ return @bitCast(c_ushort, @truncate(c_short, x));
23792276 \\}
23802277 });
23812278
2382 cases.add("do while with empty body",
2383 \\void foo(void) {
2384 \\ do ; while (1);
2279 cases.add("arg name aliasing decl which comes after",
2280 \\int foo(int bar) {
2281 \\ bar = 2;
23852282 \\}
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 \\ }
2283 \\int bar = 4;
2284 , &[_][]const u8{
2285 \\pub export fn foo(arg_bar_1: c_int) c_int {
2286 \\ var bar_1 = arg_bar_1;
2287 \\ bar_1 = 2;
23922288 \\}
2289 \\pub export var bar: c_int = 4;
23932290 });
23942291
2395 cases.add("for with empty body",
2396 \\void foo(void) {
2397 \\ for (;;);
2292 cases.add("arg name aliasing macro which comes after",
2293 \\int foo(int bar) {
2294 \\ bar = 2;
23982295 \\}
2296 \\#define bar 4
23992297 , &[_][]const u8{
2400 \\pub fn foo() void {
2401 \\ while (true) {}
2298 \\pub export fn foo(arg_bar_1: c_int) c_int {
2299 \\ var bar_1 = arg_bar_1;
2300 \\ bar_1 = 2;
24022301 \\}
2302 ,
2303 \\pub const bar = 4;
24032304 });
24042305
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 \\};
2306 cases.add("don't export inline functions",
2307 \\inline void a(void) {}
2308 \\static void b(void) {}
2309 \\void c(void) {}
31822310 , &[_][]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;
2311 \\pub fn a() void {}
2312 \\pub fn b() void {}
2313 \\pub export fn c() void {}
31962314 });
31972315}