authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 22:29:42+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-18 22:29:42+02:00
logcf7a5b7a4a77181a4c90fc9a92df496cfb48c3cd
treec8614c7c0d818c2e787068498984792d7b70be00
parente65b9e8f7bcc38943f48ed44560a22c62ca222ce
signature Commit is signed but in an unrecognized format.

translate-c-2 member access


4 files changed, 154 insertions(+), 105 deletions(-)

src-self-hosted/c_tokenizer.zig+55-53
......@@ -27,6 +27,7 @@ pub const CToken = struct {
2727 Lt,
2828 Comma,
2929 Fn,
30 Arrow,
3031 };
3132
3233 pub const NumLitSuffix = enum {
......@@ -164,6 +165,8 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
164165 NumLitIntSuffixL,
165166 NumLitIntSuffixLL,
166167 NumLitIntSuffixUL,
168 Minus,
169 Done,
167170 } = .Start;
168171
169172 var result = CToken{
......@@ -178,9 +181,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
178181 const c = chars[i.*];
179182 if (c == 0) {
180183 switch (state) {
181 .Start => {
182 return result;
183 },
184184 .Identifier,
185185 .Decimal,
186186 .Hex,
......@@ -193,6 +193,9 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
193193 result.bytes = chars[begin_index..i.*];
194194 return result;
195195 },
196 .Start,
197 .Minus,
198 .Done,
196199 .NumLitIntSuffixU,
197200 .NumLitIntSuffixL,
198201 .NumLitIntSuffixUL,
......@@ -212,7 +215,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
212215 => return error.TokenizingFailed,
213216 }
214217 }
215 i.* += 1;
216218 switch (state) {
217219 .Start => {
218220 switch (c) {
......@@ -220,12 +222,12 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
220222 '\'' => {
221223 state = .CharLit;
222224 result.id = .CharLit;
223 begin_index = i.* - 1;
225 begin_index = i.*;
224226 },
225227 '\"' => {
226228 state = .String;
227229 result.id = .StrLit;
228 begin_index = i.* - 1;
230 begin_index = i.*;
229231 },
230232 '/' => {
231233 state = .OpenComment;
......@@ -239,21 +241,21 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
239241 'a'...'z', 'A'...'Z', '_' => {
240242 state = .Identifier;
241243 result.id = .Identifier;
242 begin_index = i.* - 1;
244 begin_index = i.*;
243245 },
244246 '1'...'9' => {
245247 state = .Decimal;
246248 result.id = .NumLitInt;
247 begin_index = i.* - 1;
249 begin_index = i.*;
248250 },
249251 '0' => {
250252 state = .GotZero;
251253 result.id = .NumLitInt;
252 begin_index = i.* - 1;
254 begin_index = i.*;
253255 },
254256 '.' => {
255257 result.id = .Dot;
256 return result;
258 state = .Done;
257259 },
258260 '<' => {
259261 result.id = .Lt;
......@@ -261,40 +263,52 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
261263 },
262264 '(' => {
263265 result.id = .LParen;
264 return result;
266 state = .Done;
265267 },
266268 ')' => {
267269 result.id = .RParen;
268 return result;
270 state = .Done;
269271 },
270272 '*' => {
271273 result.id = .Asterisk;
272 return result;
274 state = .Done;
273275 },
274276 '-' => {
277 state = .Minus;
275278 result.id = .Minus;
276 return result;
277279 },
278280 '!' => {
279281 result.id = .Bang;
280 return result;
282 state = .Done;
281283 },
282284 '~' => {
283285 result.id = .Tilde;
284 return result;
286 state = .Done;
285287 },
286288 ',' => {
287289 result.id = .Comma;
288 return result;
290 state = .Done;
289291 },
290292 else => return error.TokenizingFailed,
291293 }
292294 },
295 .Done => return result,
296 .Minus => {
297 switch (c) {
298 '>' => {
299 result.id = .Arrow;
300 state = .Done;
301 },
302 else => {
303 return result;
304 },
305 }
306 },
293307 .GotLt => {
294308 switch (c) {
295309 '<' => {
296310 result.id = .Shl;
297 return result;
311 state = .Done;
298312 },
299313 else => {
300314 return result;
......@@ -310,19 +324,16 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
310324 'f',
311325 'F',
312326 => {
313 i.* -= 1;
314327 result.num_lit_suffix = .F;
315328 result.bytes = chars[begin_index..i.*];
316 return result;
329 state = .Done;
317330 },
318331 'l', 'L' => {
319 i.* -= 1;
320332 result.num_lit_suffix = .L;
321333 result.bytes = chars[begin_index..i.*];
322 return result;
334 state = .Done;
323335 },
324336 else => {
325 i.* -= 1;
326337 result.bytes = chars[begin_index..i.*];
327338 return result;
328339 },
......@@ -352,16 +363,15 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
352363 '0'...'9' => {},
353364 'f', 'F' => {
354365 result.num_lit_suffix = .F;
355 result.bytes = chars[begin_index .. i.* - 1];
356 return result;
366 result.bytes = chars[begin_index..i.*];
367 state = .Done;
357368 },
358369 'l', 'L' => {
359370 result.num_lit_suffix = .L;
360 result.bytes = chars[begin_index .. i.* - 1];
361 return result;
371 result.bytes = chars[begin_index..i.*];
372 state = .Done;
362373 },
363374 else => {
364 i.* -= 1;
365375 result.bytes = chars[begin_index..i.*];
366376 return result;
367377 },
......@@ -374,19 +384,18 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
374384 'u', 'U' => {
375385 state = .NumLitIntSuffixU;
376386 result.num_lit_suffix = .U;
377 result.bytes = chars[begin_index .. i.* - 1];
387 result.bytes = chars[begin_index..i.*];
378388 },
379389 'l', 'L' => {
380390 state = .NumLitIntSuffixL;
381391 result.num_lit_suffix = .L;
382 result.bytes = chars[begin_index .. i.* - 1];
392 result.bytes = chars[begin_index..i.*];
383393 },
384394 '.' => {
385395 result.id = .NumLitFloat;
386396 state = .Float;
387397 },
388398 else => {
389 i.* -= 1;
390399 result.bytes = chars[begin_index..i.*];
391400 return result;
392401 },
......@@ -407,12 +416,12 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
407416 'u', 'U' => {
408417 state = .NumLitIntSuffixU;
409418 result.num_lit_suffix = .U;
410 result.bytes = chars[begin_index .. i.* - 1];
419 result.bytes = chars[begin_index..i.*];
411420 },
412421 'l', 'L' => {
413422 state = .NumLitIntSuffixL;
414423 result.num_lit_suffix = .L;
415 result.bytes = chars[begin_index .. i.* - 1];
424 result.bytes = chars[begin_index..i.*];
416425 },
417426 else => {
418427 i.* -= 1;
......@@ -425,7 +434,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
425434 '0'...'7' => {},
426435 '8', '9' => return error.TokenizingFailed,
427436 else => {
428 i.* -= 1;
429437 result.bytes = chars[begin_index..i.*];
430438 return result;
431439 },
......@@ -438,16 +446,15 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
438446 // marks the number literal as unsigned
439447 state = .NumLitIntSuffixU;
440448 result.num_lit_suffix = .U;
441 result.bytes = chars[begin_index .. i.* - 1];
449 result.bytes = chars[begin_index..i.*];
442450 },
443451 'l', 'L' => {
444452 // marks the number literal as long
445453 state = .NumLitIntSuffixL;
446454 result.num_lit_suffix = .L;
447 result.bytes = chars[begin_index .. i.* - 1];
455 result.bytes = chars[begin_index..i.*];
448456 },
449457 else => {
450 i.* -= 1;
451458 result.bytes = chars[begin_index..i.*];
452459 return result;
453460 },
......@@ -461,16 +468,15 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
461468 // marks the number literal as unsigned
462469 state = .NumLitIntSuffixU;
463470 result.num_lit_suffix = .U;
464 result.bytes = chars[begin_index .. i.* - 1];
471 result.bytes = chars[begin_index..i.*];
465472 },
466473 'l', 'L' => {
467474 // marks the number literal as long
468475 state = .NumLitIntSuffixL;
469476 result.num_lit_suffix = .L;
470 result.bytes = chars[begin_index .. i.* - 1];
477 result.bytes = chars[begin_index..i.*];
471478 },
472479 else => {
473 i.* -= 1;
474480 result.bytes = chars[begin_index..i.*];
475481 return result;
476482 },
......@@ -483,7 +489,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
483489 state = .NumLitIntSuffixUL;
484490 },
485491 else => {
486 i.* -= 1;
487492 return result;
488493 },
489494 }
......@@ -496,10 +501,9 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
496501 },
497502 'u', 'U' => {
498503 result.num_lit_suffix = .LU;
499 return result;
504 state = .Done;
500505 },
501506 else => {
502 i.* -= 1;
503507 return result;
504508 },
505509 }
......@@ -508,10 +512,9 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
508512 switch (c) {
509513 'u', 'U' => {
510514 result.num_lit_suffix = .LLU;
511 return result;
515 state = .Done;
512516 },
513517 else => {
514 i.* -= 1;
515518 return result;
516519 },
517520 }
......@@ -523,7 +526,6 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
523526 return result;
524527 },
525528 else => {
526 i.* -= 1;
527529 return result;
528530 },
529531 }
......@@ -532,17 +534,16 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
532534 switch (c) {
533535 '_', 'a'...'z', 'A'...'Z', '0'...'9' => {},
534536 else => {
535 i.* -= 1;
536537 result.bytes = chars[begin_index..i.*];
537538 return result;
538539 },
539540 }
540541 },
541 .String => { // TODO char escapes
542 .String => {
542543 switch (c) {
543544 '\"' => {
544 result.bytes = chars[begin_index..i.*];
545 return result;
545 result.bytes = chars[begin_index .. i.* + 1];
546 state = .Done;
546547 },
547548 else => {},
548549 }
......@@ -550,8 +551,8 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
550551 .CharLit => {
551552 switch (c) {
552553 '\'' => {
553 result.bytes = chars[begin_index..i.*];
554 return result;
554 result.bytes = chars[begin_index .. i.* + 1];
555 state = .Done;
555556 },
556557 else => {},
557558 }
......@@ -566,7 +567,7 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
566567 },
567568 else => {
568569 result.id = .Slash;
569 return result;
570 state = .Done;
570571 },
571572 }
572573 },
......@@ -598,6 +599,7 @@ fn next(chars: [*:0]const u8, i: *usize) !CToken {
598599 }
599600 },
600601 }
602 i.* += 1;
601603 }
602604 unreachable;
603605}
src-self-hosted/clang.zig+5-1
......@@ -1096,5 +1096,9 @@ pub extern fn ZigClangCharacterLiteral_getBeginLoc(*const ZigClangCharacterLiter
10961096pub extern fn ZigClangCharacterLiteral_getKind(*const ZigClangCharacterLiteral) ZigClangCharacterLiteral_CharacterKind;
10971097pub extern fn ZigClangCharacterLiteral_getValue(*const ZigClangCharacterLiteral) c_uint;
10981098
1099pub extern fn ZigClangStmtExpr_getSubStmt( *const ZigClangStmtExpr) *const ZigClangCompoundStmt;
1099pub extern fn ZigClangStmtExpr_getSubStmt(*const ZigClangStmtExpr) *const ZigClangCompoundStmt;
1100
1101pub extern fn ZigClangMemberExpr_getBase(*const ZigClangMemberExpr) *const ZigClangExpr;
1102pub extern fn ZigClangMemberExpr_isArrow(*const ZigClangMemberExpr) bool;
1103pub extern fn ZigClangMemberExpr_getMemberDecl(*const ZigClangMemberExpr) *const ZigClangValueDecl;
11001104
src-self-hosted/translate_c.zig+49-35
......@@ -49,9 +49,6 @@ const Scope = struct {
4949 Root,
5050 Condition,
5151 FnDef,
52
53 /// used when getting a member `a.b`
54 Ref,
5552 Loop,
5653 };
5754
......@@ -181,7 +178,6 @@ const Scope = struct {
181178 fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 {
182179 return switch (scope.id) {
183180 .Root => null,
184 .Ref => null,
185181 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
186182 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
187183 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
......@@ -190,7 +186,6 @@ const Scope = struct {
190186
191187 fn contains(scope: *Scope, name: []const u8) bool {
192188 return switch (scope.id) {
193 .Ref => false,
194189 .Root => @fieldParentPtr(Root, "base", scope).contains(name),
195190 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
196191 .Block => @fieldParentPtr(Block, "base", scope).contains(name),
......@@ -230,7 +225,6 @@ const Context = struct {
230225 decl_table: DeclTable,
231226 alias_list: AliasList,
232227 global_scope: *Scope.Root,
233 ptr_params: std.BufSet,
234228 clang_context: *ZigClangASTContext,
235229 mangle_count: u64 = 0,
236230
......@@ -316,7 +310,6 @@ pub fn translate(
316310 .decl_table = DeclTable.init(arena),
317311 .alias_list = AliasList.init(arena),
318312 .global_scope = try arena.create(Scope.Root),
319 .ptr_params = std.BufSet.init(arena),
320313 .clang_context = ZigClangASTUnit_getASTContext(ast_unit).?,
321314 };
322315 context.global_scope.* = Scope.Root.init(&context);
......@@ -856,6 +849,7 @@ fn transStmt(
856849 .PredefinedExprClass => return transPredefinedExpr(rp, scope, @ptrCast(*const ZigClangPredefinedExpr, stmt), result_used),
857850 .CharacterLiteralClass => return transCharLiteral(rp, scope, @ptrCast(*const ZigClangCharacterLiteral, stmt), result_used),
858851 .StmtExprClass => return transStmtExpr(rp, scope, @ptrCast(*const ZigClangStmtExpr, stmt), result_used),
852 .MemberExprClass => return transMemberExpr(rp, scope, @ptrCast(*const ZigClangMemberExpr, stmt), result_used),
859853 else => {
860854 return revertAndWarn(
861855 rp,
......@@ -1147,7 +1141,6 @@ fn transDeclRefExpr(
11471141 const value_decl = ZigClangDeclRefExpr_getDecl(expr);
11481142 const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, value_decl)));
11491143 const checked_name = if (scope.getAlias(name)) |a| a else name;
1150 if (lrvalue == .l_value) try rp.c.ptr_params.put(checked_name);
11511144 return transCreateNodeIdentifier(rp.c, checked_name);
11521145}
11531146
......@@ -1990,6 +1983,18 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
19901983 return maybeSuppressResult(rp, scope, used, &grouped_expr.base);
19911984}
19921985
1986fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberExpr, result_used: ResultUsed) TransError!*ast.Node {
1987 var container_node = try transExpr(rp, scope, ZigClangMemberExpr_getBase(stmt), .used, .r_value);
1988
1989 if (ZigClangMemberExpr_isArrow(stmt)) {
1990 container_node = try transCreateNodePtrDeref(rp.c, container_node);
1991 }
1992
1993 const name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, ZigClangMemberExpr_getMemberDecl(stmt))));
1994 const node = try transCreateNodeFieldAccess(rp.c, container_node, name);
1995 return maybeSuppressResult(rp, scope, result_used, node);
1996}
1997
19931998fn transCPtrCast(
19941999 rp: RestorePoint,
19952000 loc: ZigClangSourceLocation,
......@@ -2213,8 +2218,8 @@ fn qualTypeToLog2IntRef(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigC
22132218 import_fn_call.rparen_token = try appendToken(rp.c, .RParen, ")");
22142219
22152220 const inner_field_access = try transCreateNodeFieldAccess(rp.c, &import_fn_call.base, "math");
2216 const outer_field_access = try transCreateNodeFieldAccess(rp.c, &inner_field_access.base, "Log2Int");
2217 const log2int_fn_call = try transCreateNodeFnCall(rp.c, &outer_field_access.base);
2221 const outer_field_access = try transCreateNodeFieldAccess(rp.c, inner_field_access, "Log2Int");
2222 const log2int_fn_call = try transCreateNodeFnCall(rp.c, outer_field_access);
22182223 try @ptrCast(*ast.Node.SuffixOp.Op.Call, &log2int_fn_call.op).params.push(zig_type_node);
22192224 log2int_fn_call.rtoken = try appendToken(rp.c, .RParen, ")");
22202225
......@@ -2446,7 +2451,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {
24462451 return node;
24472452}
24482453
2449fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node.InfixOp {
2454fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node {
24502455 const field_access_node = try c.a().create(ast.Node.InfixOp);
24512456 field_access_node.* = .{
24522457 .op_token = try appendToken(c, .Period, "."),
......@@ -2454,7 +2459,7 @@ fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []c
24542459 .op = .Period,
24552460 .rhs = try transCreateNodeIdentifier(c, field_name),
24562461 };
2457 return field_access_node;
2462 return &field_access_node.base;
24582463}
24592464
24602465fn transCreateNodePrefixOp(
......@@ -2924,9 +2929,9 @@ fn transCreateNodeShiftOp(
29242929 rp: RestorePoint,
29252930 scope: *Scope,
29262931 stmt: *const ZigClangBinaryOperator,
2927 comptime op: ast.Node.InfixOp.Op,
2928 comptime op_tok_id: std.zig.Token.Id,
2929 comptime bytes: []const u8,
2932 op: ast.Node.InfixOp.Op,
2933 op_tok_id: std.zig.Token.Id,
2934 bytes: []const u8,
29302935) !*ast.Node {
29312936 std.debug.assert(op == .BitShiftLeft or op == .BitShiftRight);
29322937
......@@ -2957,6 +2962,16 @@ fn transCreateNodeShiftOp(
29572962 return &node.base;
29582963}
29592964
2965fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node {
2966 const node = try c.a().create(ast.Node.SuffixOp);
2967 node.* = .{
2968 .lhs = .{ .node = lhs },
2969 .op = .Deref,
2970 .rtoken = try appendToken(c, .PeriodAsterisk, ".*"),
2971 };
2972 return &node.base;
2973}
2974
29602975const RestorePoint = struct {
29612976 c: *Context,
29622977 token_index: ast.TokenIndex,
......@@ -3862,16 +3877,21 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
38623877 .{},
38633878 );
38643879
3865 const op_token = try appendToken(rp.c, .Period, ".");
3866 const rhs = try transCreateNodeIdentifier(rp.c, name_tok.bytes);
3867 const access_node = try rp.c.a().create(ast.Node.InfixOp);
3868 access_node.* = .{
3869 .op_token = op_token,
3870 .lhs = node,
3871 .op = .Period,
3872 .rhs = rhs,
3873 };
3874 node = &access_node.base;
3880 node = try transCreateNodeFieldAccess(rp.c, node, name_tok.bytes);
3881 },
3882 .Arrow => {
3883 const name_tok = it.next().?;
3884 if (name_tok.id != .Identifier)
3885 return revertAndWarn(
3886 rp,
3887 error.ParseError,
3888 source_loc,
3889 "unable to translate C expr",
3890 .{},
3891 );
3892
3893 const deref = try transCreateNodePtrDeref(rp.c, node);
3894 node = try transCreateNodeFieldAccess(rp.c, deref, name_tok.bytes);
38753895 },
38763896 .Asterisk => {
38773897 if (it.peek().?.id == .RParen) {
......@@ -3887,14 +3907,14 @@ fn parseCSuffixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
38873907 // expr * expr
38883908 const op_token = try appendToken(rp.c, .Asterisk, "*");
38893909 const rhs = try parseCPrimaryExpr(rp, it, source_loc, scope);
3890 const bitshift_node = try rp.c.a().create(ast.Node.InfixOp);
3891 bitshift_node.* = .{
3910 const mul_node = try rp.c.a().create(ast.Node.InfixOp);
3911 mul_node.* = .{
38923912 .op_token = op_token,
38933913 .lhs = node,
38943914 .op = .BitShiftLeft,
38953915 .rhs = rhs,
38963916 };
3897 node = &bitshift_node.base;
3917 node = &mul_node.base;
38983918 }
38993919 },
39003920 .Shl => {
......@@ -3938,13 +3958,7 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
39383958 },
39393959 .Asterisk => {
39403960 const prefix_op_expr = try parseCPrefixOpExpr(rp, it, source_loc, scope);
3941 const node = try rp.c.a().create(ast.Node.SuffixOp);
3942 node.* = .{
3943 .lhs = .{ .node = prefix_op_expr },
3944 .op = .Deref,
3945 .rtoken = try appendToken(rp.c, .PeriodAsterisk, ".*"),
3946 };
3947 return &node.base;
3961 return try transCreateNodePtrDeref(rp.c, prefix_op_expr);
39483962 },
39493963 else => {
39503964 _ = it.prev();
test/translate_c.zig+45-16
......@@ -1494,6 +1494,35 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14941494 \\}
14951495 });
14961496
1497 cases.add_2("field access expression",
1498 \\#define ARROW a->b
1499 \\#define DOT a.b
1500 \\extern struct Foo {
1501 \\ int b;
1502 \\}a;
1503 \\float b = 2.0f;
1504 \\int foo(void) {
1505 \\ struct Foo *c;
1506 \\ a.b;
1507 \\ c->b;
1508 \\}
1509 , &[_][]const u8{
1510 \\pub const struct_Foo = extern struct {
1511 \\ b: c_int,
1512 \\};
1513 \\pub extern var a: struct_Foo;
1514 \\pub export var b: f32 = 2;
1515 \\pub export fn foo() c_int {
1516 \\ var c: [*c]struct_Foo = undefined;
1517 \\ _ = a.b;
1518 \\ _ = c.*.b;
1519 \\}
1520 ,
1521 \\pub const DOT = a.b;
1522 ,
1523 \\pub const ARROW = a.*.b;
1524 });
1525
14971526 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
14981527
14991528 cases.addAllowWarnings("simple data types",
......@@ -1702,22 +1731,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17021731 \\}
17031732 });
17041733
1705 cases.addC("field access expression",
1706 \\struct Foo {
1707 \\ int field;
1708 \\};
1709 \\int read_field(struct Foo *foo) {
1710 \\ return foo->field;
1711 \\}
1712 , &[_][]const u8{
1713 \\pub const struct_Foo = extern struct {
1714 \\ field: c_int,
1715 \\};
1716 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
1717 \\ return foo.*.field;
1718 \\}
1719 });
1720
17211734 cases.addC("array access",
17221735 \\int array[100];
17231736 \\int foo(int index) {
......@@ -2627,4 +2640,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
26272640 \\ };
26282641 \\}
26292642 });
2643
2644 cases.addC("field access expression",
2645 \\struct Foo {
2646 \\ int field;
2647 \\};
2648 \\int read_field(struct Foo *foo) {
2649 \\ return foo->field;
2650 \\}
2651 , &[_][]const u8{
2652 \\pub const struct_Foo = extern struct {
2653 \\ field: c_int,
2654 \\};
2655 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
2656 \\ return foo.*.field;
2657 \\}
2658 });
26302659}