mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
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.
This commit is contained in:
parent
39ee3bc0ec
commit
5749f706ef
@ -2213,32 +2213,32 @@ fn transUnaryExprOrTypeTraitExpr(
|
||||
return maybeSuppressResult(rp, scope, result_used, &builtin_node.base);
|
||||
}
|
||||
|
||||
fn qualTypeHaswrappingOverflow(qt: ZigClangQualType) bool {
|
||||
if (cIsSignedInteger(qt) or cIsFloating(qt)) {
|
||||
// float and signed integer overflow is undefined behavior.
|
||||
return false;
|
||||
} else {
|
||||
fn qualTypeHasWrappingOverflow(qt: ZigClangQualType) bool {
|
||||
if (cIsUnsignedInteger(qt)) {
|
||||
// unsigned integer overflow wraps around.
|
||||
return true;
|
||||
} else {
|
||||
// float, signed integer, and pointer overflow is undefined behavior.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnaryOperator, used: ResultUsed) TransError!*ast.Node {
|
||||
const op_expr = ZigClangUnaryOperator_getSubExpr(stmt);
|
||||
switch (ZigClangUnaryOperator_getOpcode(stmt)) {
|
||||
.PostInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
.PostInc => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
|
||||
else
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
|
||||
.PostDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
.PostDec => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
|
||||
else
|
||||
return transCreatePostCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
|
||||
.PreInc => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
.PreInc => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", used)
|
||||
else
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", used),
|
||||
.PreDec => if (qualTypeHaswrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
.PreDec => if (qualTypeHasWrappingOverflow(ZigClangUnaryOperator_getType(stmt)))
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", used)
|
||||
else
|
||||
return transCreatePreCrement(rp, scope, stmt, .AssignSub, .MinusEqual, "-=", used),
|
||||
@ -2258,7 +2258,7 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
|
||||
},
|
||||
.Plus => return transExpr(rp, scope, op_expr, used, .r_value),
|
||||
.Minus => {
|
||||
if (!qualTypeHaswrappingOverflow(ZigClangExpr_getType(op_expr))) {
|
||||
if (!qualTypeHasWrappingOverflow(ZigClangExpr_getType(op_expr))) {
|
||||
const op_node = try transCreateNodePrefixOp(rp.c, .Negation, .Minus, "-");
|
||||
op_node.rhs = try transExpr(rp, scope, op_expr, .used, .r_value);
|
||||
return &op_node.base;
|
||||
@ -2426,15 +2426,15 @@ fn transCreatePostCrement(
|
||||
|
||||
fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
|
||||
switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
|
||||
.MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
.MulAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MulWrap, .AsteriskPercent, "*%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used),
|
||||
.AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
.AddAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignAdd, .PlusEqual, "+=", .Add, .Plus, "+", used),
|
||||
.SubAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
.SubAssign => if (qualTypeHasWrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignSubWrap, .MinusPercentEqual, "-%=", .SubWrap, .MinusPercent, "-%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignSub, .MinusPercentEqual, "-=", .Sub, .Minus, "-", used),
|
||||
|
||||
@ -1777,6 +1777,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ a++;
|
||||
\\ return a;
|
||||
\\}
|
||||
\\int *foo3(int *a) {
|
||||
\\ a++;
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo1(_arg_a_1: c_uint) c_uint {
|
||||
\\ var a_1 = _arg_a_1;
|
||||
@ -1788,6 +1792,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ a_2 += 1;
|
||||
\\ return a_2;
|
||||
\\}
|
||||
\\pub export fn foo3(_arg_a_3: [*c]c_int) [*c]c_int {
|
||||
\\ var a_3 = _arg_a_3;
|
||||
\\ a_3 += 1;
|
||||
\\ return a_3;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("deref function pointer",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user