Better handling of decayed arrays to pointers

This commit is contained in:
LemonBoy 2020-01-06 17:11:10 +01:00 committed by Andrew Kelley
parent 0deab8fd3b
commit 7e7d0e1ffa
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 40 additions and 2 deletions

View File

@ -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, "]");

View File

@ -70,4 +70,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
cases.add("array to pointer decay",
\\#include <stdlib.h>
\\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;
\\}
, "");
}