authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-01-06 17:11:10+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-01-06 19:32:53-05:00
log7e7d0e1ffaaee4f3deb49d3b98ffd5fcefaf85b1
treeb687c73d357a182e1f2ecca3091df71820f21005
parent0deab8fd3bba3fa25ab70f6cf2e04b234aba8eb4
signature Commit is signed but in an unrecognized format.

Better handling of decayed arrays to pointers


2 files changed, 40 insertions(+), 2 deletions(-)

src-self-hosted/translate_c.zig+27-2
...@@ -1334,9 +1334,22 @@ fn transImplicitCastExpr(...@@ -1334,9 +1334,22 @@ fn transImplicitCastExpr(
1334 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {1334 .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => {
1335 return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node);1335 return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node);
1336 },1336 },
1337 .LValueToRValue, .NoOp, .FunctionToPointerDecay, .ArrayToPointerDecay => {1337 .LValueToRValue, .NoOp, .FunctionToPointerDecay => {
1338 return maybeSuppressResult(rp, scope, result_used, sub_expr_node);1338 return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
1339 },1339 },
1340 .ArrayToPointerDecay => {
1341 switch (ZigClangExpr_getStmtClass(sub_expr)) {
1342 .StringLiteralClass, .PredefinedExprClass => {
1343 return maybeSuppressResult(rp, scope, result_used, sub_expr_node);
1344 },
1345 else => {
1346 const prefix_op = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&");
1347 prefix_op.rhs = sub_expr_node;
1348
1349 return maybeSuppressResult(rp, scope, result_used, &prefix_op.base);
1350 },
1351 }
1352 },
1340 .NullToPointer => {1353 .NullToPointer => {
1341 return try transCreateNodeNullLiteral(rp.c);1354 return try transCreateNodeNullLiteral(rp.c);
1342 },1355 },
...@@ -2469,7 +2482,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE...@@ -2469,7 +2482,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE
2469}2482}
24702483
2471fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArraySubscriptExpr, result_used: ResultUsed) TransError!*ast.Node {2484fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArraySubscriptExpr, result_used: ResultUsed) TransError!*ast.Node {
2472 const container_node = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getBase(stmt), .used, .r_value);2485 var base_stmt = ZigClangArraySubscriptExpr_getBase(stmt);
2486
2487 // Unwrap the base statement if it's an array decayed to a bare pointer type
2488 // so that we index the array itself
2489 if (ZigClangStmt_getStmtClass(@ptrCast(*const ZigClangStmt, base_stmt)) == .ImplicitCastExprClass) {
2490 const implicit_cast = @ptrCast(*const ZigClangImplicitCastExpr, base_stmt);
2491
2492 if (ZigClangImplicitCastExpr_getCastKind(implicit_cast) == .ArrayToPointerDecay) {
2493 base_stmt = ZigClangImplicitCastExpr_getSubExpr(implicit_cast);
2494 }
2495 }
2496
2497 const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value);
2473 const node = try transCreateNodeArrayAccess(rp.c, container_node);2498 const node = try transCreateNodeArrayAccess(rp.c, container_node);
2474 node.op.ArrayAccess = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getIdx(stmt), .used, .r_value);2499 node.op.ArrayAccess = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getIdx(stmt), .used, .r_value);
2475 node.rtoken = try appendToken(rp.c, .RBrace, "]");2500 node.rtoken = try appendToken(rp.c, .RBrace, "]");
test/run_translated_c.zig+13
...@@ -70,4 +70,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -70,4 +70,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
70 \\ return 0;70 \\ return 0;
71 \\}71 \\}
72 , "");72 , "");
73
74 cases.add("array to pointer decay",
75 \\#include <stdlib.h>
76 \\int main(int argc, char **argv) {
77 \\ char data[3] = {'a','b','c'};
78 \\ if (2[data] != data[2]) abort();
79 \\ if ("abc"[1] != data[1]) abort();
80 \\ char *as_ptr = data;
81 \\ if (2[as_ptr] != as_ptr[2]) abort();
82 \\ if ("abc"[1] != as_ptr[1]) abort();
83 \\ return 0;
84 \\}
85 , "");
73}86}