authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-31 17:33:55-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-31 17:33:55-05:00
log5749f706ef866b3c77d6fb8fda9ed08e5c118f58
tree0f69b721e1728851a685b2596d98c63b88654488
parent39ee3bc0ecdfde43e6fa98ee454a0115b3cb7390
signature Commit is signed but in an unrecognized format.

translate-c: non-wrapping operator for pointer arithmetic

According to C11 6.5.6.8, pointer arithmetic may not overflow. In fact, it may not even go more than 1 past the end of an object, or UB occurs. This is the same as Zig pointer arithmetic semantics, and so the `+` and `+=` operators rather than `+%` and `+%=` are appropriate for C-translated pointer arithmetic.

2 files changed, 22 insertions(+), 13 deletions(-)

src-self-hosted/translate_c.zig+13-13
......@@ -2213,32 +2213,32 @@ fn transUnaryExprOrTypeTraitExpr(
22132213 return maybeSuppressResult(rp, scope, result_used, &builtin_node.base);
22142214}
22152215
2216fn qualTypeHaswrappingOverflow(qt: ZigClangQualType) bool {
2217 if (cIsSignedInteger(qt) or cIsFloating(qt)) {
2218 // float and signed integer overflow is undefined behavior.
2219 return false;
2220 } else {
2216fn qualTypeHasWrappingOverflow(qt: ZigClangQualType) bool {
2217 if (cIsUnsignedInteger(qt)) {
22212218 // unsigned integer overflow wraps around.
22222219 return true;
2220 } else {
2221 // float, signed integer, and pointer overflow is undefined behavior.
2222 return false;
22232223 }
22242224}
22252225
22262226fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnaryOperator, used: ResultUsed) TransError!*ast.Node {
22272227 const op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
22282228 switch (ZigClangUnaryOperator_getOpcode(stmt)) {
2229 .PostInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2229 .PostInc => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22302230 return transCreatePostCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
22312231 else
22322232 return transCreatePostCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
2233 .PostDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2233 .PostDec => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22342234 return transCreatePostCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
22352235 else
22362236 return transCreatePostCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
2237 .PreInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2237 .PreInc => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22382238 return transCreatePreCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
22392239 else
22402240 return transCreatePreCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
2241 .PreDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
2241 .PreDec => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
22422242 return transCreatePreCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
22432243 else
22442244 return transCreatePreCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
......@@ -2258,7 +2258,7 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
22582258 },
22592259 .Plus => return transExpr(rp, scope, op_expr, used, .r_value),
22602260 .Minus => {
2261 if (!qualTypeHaswrappingOverflow(ZigClangExpr_getType(op_expr))) {
2261 if (!qualTypeHasWrappingOverflow(ZigClangExpr_getType(op_expr))) {
22622262 const op_node = try transCreateNodePrefixOp(rp.c, .Negation, .Minus, "-");
22632263 op_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value);
22642264 return &op_node.base;
......@@ -2426,15 +2426,15 @@ fn transCreatePostCrement(
24262426
24272427fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
24282428 switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
2429 .MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2429 .MulAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
24302430 return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MulWrap, .AsteriskPercent, "*%", used)
24312431 else
24322432 return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used),
2433 .AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2433 .AddAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
24342434 return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
24352435 else
24362436 return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used),
2437 .SubAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2437 .SubAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
24382438 return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
24392439 else
24402440 return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
test/translate_c.zig+9
......@@ -1777,6 +1777,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17771777 \\ a++;
17781778 \\ return a;
17791779 \\}
1780 \\int *foo3(int *a) {
1781 \\ a++;
1782 \\ return a;
1783 \\}
17801784 , &[_][]const u8{
17811785 \\pub export fn foo1(_arg_a_1: c_uint) c_uint {
17821786 \\ var a_1 = _arg_a_1;
......@@ -1788,6 +1792,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17881792 \\ a_2 += 1;
17891793 \\ return a_2;
17901794 \\}
1795 \\pub export fn foo3(_arg_a_3: [*c]c_int) [*c]c_int {
1796 \\ var a_3 = _arg_a_3;
1797 \\ a_3 += 1;
1798 \\ return a_3;
1799 \\}
17911800 });
17921801
17931802 cases.add("deref function pointer",