From 39f487435e6aea87e33e9dd085e0b3b7bb9afdd9 Mon Sep 17 00:00:00 2001 From: Andy Balholm Date: Mon, 3 Dec 2018 19:21:58 -0800 Subject: [PATCH] Support incrementing a MemberExpr that is is a pointer. Fixes #811 (#812) For example, if a is a char **, now we can transpile ++*a. --- noarch/stdio.go | 2 +- tests/operators.c | 23 ++++++++++++++++++++++- transpiler/unary.go | 30 ++++++++++++++++++++---------- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/noarch/stdio.go b/noarch/stdio.go index aca3e33b6..6c0c7e9a6 100644 --- a/noarch/stdio.go +++ b/noarch/stdio.go @@ -112,7 +112,7 @@ func Fopen(filePath, mode *byte) *File { err = file.Truncate(0) } default: - panic(fmt.Sprintf("unsupported file mode: %s", mode)) + panic(fmt.Sprintf("unsupported file mode: %s", m)) } if err != nil { diff --git a/tests/operators.c b/tests/operators.c index 446d9d4d6..98258e5d8 100644 --- a/tests/operators.c +++ b/tests/operators.c @@ -48,9 +48,13 @@ typedef unsigned char pcre_uchar; #define PREP_A 0x0002 #define PREP_B 0x0010 +void unusedInt(int n) { + ; +} + int main() { - plan(140); + plan(142); int i = 10; signed char j = 1; @@ -371,6 +375,7 @@ int main() } { int yy = 0; + unusedInt(yy); if ((yy = simple_repeat(42)) > 3) { pass("ok") @@ -505,6 +510,22 @@ int main() flags &= ~(PREP_A|PREP_B); is_eq(flags, 32); } + diag("Increment pointer in struct"); + { + struct aStruct { + char *a; + } v; + v.a = "Hello"; + ++v.a; + is_streq(v.a, "ello"); + } + diag("Increment pointer via poiter"); + { + char *s = "World"; + char **p = &s; + ++*p; + is_streq(s, "orld"); + } done_testing(); } diff --git a/transpiler/unary.go b/transpiler/unary.go index 13d0e10d4..8b75915a0 100644 --- a/transpiler/unary.go +++ b/transpiler/unary.go @@ -35,8 +35,8 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato case token.DEC: operator = token.SUB } - var declRefExpr *ast.DeclRefExpr - declRefExpr, err = getSoleChildDeclRefExpr(n) + var e ast.Node + e, err = getSoleChildIncrementable(n) if err != nil { return } @@ -44,7 +44,7 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato var left goast.Expr var leftType string var newPre, newPost []goast.Stmt - left, leftType, newPre, newPost, err = transpileToExpr(declRefExpr, p, false) + left, leftType, newPre, newPost, err = transpileToExpr(e, p, false) if err != nil { return } @@ -67,13 +67,8 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost) - var name string - name, err = getName(p, n.Children()[0]) - if err != nil { - return - } expr = &goast.BinaryExpr{ - X: goast.NewIdent(name), + X: left, Op: token.ASSIGN, Y: expr, } @@ -85,7 +80,7 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato } expr = util.NewAnonymousFunction([]goast.Stmt{&goast.ExprStmt{ X: expr, - }}, nil, goast.NewIdent(name), lType) + }}, nil, left, lType) } return } @@ -133,6 +128,21 @@ func transpileUnaryOperatorInc(n *ast.UnaryOperator, p *program.Program, operato }, p, exprIsStmt) } +func getSoleChildIncrementable(n ast.Node) (result ast.Node, err error) { + children := n.Children() + if len(children) != 1 { + return nil, fmt.Errorf("expected one child node, got %d", len(children)) + } + switch c := children[0].(type) { + case *ast.ParenExpr: + return getSoleChildIncrementable(c) + case *ast.DeclRefExpr, *ast.MemberExpr, *ast.UnaryOperator: + return c, nil + default: + return nil, fmt.Errorf("unsupported type %T", c) + } +} + func getSoleChildDeclRefExpr(n *ast.UnaryOperator) (result *ast.DeclRefExpr, err error) { var inspect ast.Node = n for {