Skip to content

Commit

Permalink
Compound assign bit-operator with cast complement. Fixes #684 and #685 (
Browse files Browse the repository at this point in the history
  • Loading branch information
kamphaus authored and elliotchance committed Apr 30, 2018
1 parent e4188c6 commit 0288b45
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
11 changes: 10 additions & 1 deletion tests/cast.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,15 @@ void test_static_array()
is_eq('e', TEST2[3]); // can distinguish character at same column in different lines
}

void castbitwise() {
pcre_uint32 x = 0xff;
x &= ~0x3c;
is_eq(x, 0xc3);
}

int main()
{
plan(36);
plan(37);

START_TEST(cast);
START_TEST(castbool);
Expand Down Expand Up @@ -216,5 +222,8 @@ int main()
diag("Compare with static array")
test_static_array();

diag("Cast with compound assign operator")
castbitwise();

done_testing();
}
29 changes: 29 additions & 0 deletions transpiler/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/elliotchance/c2go/program"
"github.com/elliotchance/c2go/types"
"github.com/elliotchance/c2go/util"
"go/token"
)

func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, exprIsStmt bool) (
Expand All @@ -34,6 +35,9 @@ func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, expr
return
}
}
if isCastToUnsignedOfUnaryComplement(n, p) {
return swapCastAndComplement(n, p, exprIsStmt)
}
expr, exprType, preStmts, postStmts, err = transpileToExpr(n.Children()[0], p, exprIsStmt)
if err != nil {
return nil, "", nil, nil, err
Expand Down Expand Up @@ -65,6 +69,31 @@ func transpileImplicitCastExpr(n *ast.ImplicitCastExpr, p *program.Program, expr
return
}

func isCastToUnsignedOfUnaryComplement(n *ast.ImplicitCastExpr, p *program.Program) (ret bool) {
if !types.IsCInteger(p, n.Type) || !strings.Contains(n.Type, "unsigned ") {
return
}
cn, ok := n.Children()[0].(*ast.UnaryOperator)
if !ok || getTokenForOperator(cn.Operator) != token.XOR {
return
}
return types.IsCInteger(p, cn.Type) && !strings.Contains(cn.Type, "unsigned ")
}

func swapCastAndComplement(n *ast.ImplicitCastExpr, p *program.Program, exprIsStmt bool) (
expr goast.Expr,
exprType string,
preStmts []goast.Stmt,
postStmts []goast.Stmt,
err error) {
uo := n.Children()[0].(*ast.UnaryOperator)
unaryChildren := uo.ChildNodes
uo.ChildNodes = []ast.Node{n}
uo.Type = n.Type
n.ChildNodes = unaryChildren
return transpileToExpr(uo, p, exprIsStmt)
}

func transpileCStyleCastExpr(n *ast.CStyleCastExpr, p *program.Program, exprIsStmt bool) (
expr goast.Expr,
exprType string,
Expand Down
6 changes: 6 additions & 0 deletions transpiler/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ func transpileCompoundAssignOperator(
}
}

switch operator {
case token.AND_ASSIGN, token.OR_ASSIGN, token.XOR_ASSIGN, token.AND_NOT_ASSIGN:
right, err = types.CastExpr(p, right, rightType, leftType)
p.AddMessage(p.GenerateWarningMessage(err, n))
}

resolvedLeftType, err := types.ResolveType(p, leftType)
if err != nil {
p.AddMessage(p.GenerateWarningMessage(err, n))
Expand Down

0 comments on commit 0288b45

Please sign in to comment.