From 7e7d0e1ffaaee4f3deb49d3b98ffd5fcefaf85b1 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 6 Jan 2020 17:11:10 +0100 Subject: [PATCH] Better handling of decayed arrays to pointers --- src-self-hosted/translate_c.zig | 29 +++++++++++++++++++++++++++-- test/run_translated_c.zig | 13 +++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index f14fa00c60..64ea8fa62f 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -1334,9 +1334,22 @@ fn transImplicitCastExpr( .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => { return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node); }, - .LValueToRValue, .NoOp, .FunctionToPointerDecay, .ArrayToPointerDecay => { + .LValueToRValue, .NoOp, .FunctionToPointerDecay => { return maybeSuppressResult(rp, scope, result_used, sub_expr_node); }, + .ArrayToPointerDecay => { + switch (ZigClangExpr_getStmtClass(sub_expr)) { + .StringLiteralClass, .PredefinedExprClass => { + return maybeSuppressResult(rp, scope, result_used, sub_expr_node); + }, + else => { + const prefix_op = try transCreateNodePrefixOp(rp.c, .AddressOf, .Ampersand, "&"); + prefix_op.rhs = sub_expr_node; + + return maybeSuppressResult(rp, scope, result_used, &prefix_op.base); + }, + } + }, .NullToPointer => { return try transCreateNodeNullLiteral(rp.c); }, @@ -2469,7 +2482,19 @@ fn transMemberExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangMemberE } fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArraySubscriptExpr, result_used: ResultUsed) TransError!*ast.Node { - const container_node = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getBase(stmt), .used, .r_value); + var base_stmt = ZigClangArraySubscriptExpr_getBase(stmt); + + // Unwrap the base statement if it's an array decayed to a bare pointer type + // so that we index the array itself + if (ZigClangStmt_getStmtClass(@ptrCast(*const ZigClangStmt, base_stmt)) == .ImplicitCastExprClass) { + const implicit_cast = @ptrCast(*const ZigClangImplicitCastExpr, base_stmt); + + if (ZigClangImplicitCastExpr_getCastKind(implicit_cast) == .ArrayToPointerDecay) { + base_stmt = ZigClangImplicitCastExpr_getSubExpr(implicit_cast); + } + } + + const container_node = try transExpr(rp, scope, base_stmt, .used, .r_value); const node = try transCreateNodeArrayAccess(rp.c, container_node); node.op.ArrayAccess = try transExpr(rp, scope, ZigClangArraySubscriptExpr_getIdx(stmt), .used, .r_value); node.rtoken = try appendToken(rp.c, .RBrace, "]"); diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index 3ebc4b127c..0b11018118 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -70,4 +70,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); + + cases.add("array to pointer decay", + \\#include + \\int main(int argc, char **argv) { + \\ char data[3] = {'a','b','c'}; + \\ if (2[data] != data[2]) abort(); + \\ if ("abc"[1] != data[1]) abort(); + \\ char *as_ptr = data; + \\ if (2[as_ptr] != as_ptr[2]) abort(); + \\ if ("abc"[1] != as_ptr[1]) abort(); + \\ return 0; + \\} + , ""); }