Fixed pointer subtraction in certain very rare cases.

This commit is contained in:
acqn
2021-04-15 21:38:30 +08:00
committed by Oliver Schmidt
parent 6bb1b6953f
commit 6e61093e79

View File

@@ -3250,6 +3250,20 @@ static void parsesub (ExprDesc* Expr)
/* Get the rhs type */ /* Get the rhs type */
rhst = Expr2.Type; rhst = Expr2.Type;
if (IsClassPtr (lhst)) {
/* We'll have to scale the result */
rscale = PSizeOf (lhst);
/* We cannot scale by 0-size or unknown-size */
if (rscale == 0 && (IsClassPtr (rhst) || IsClassInt (rhst))) {
TypeCompatibilityDiagnostic (lhst, rhst,
1, "Invalid pointer types in subtraction: '%s' and '%s'");
/* Avoid further errors */
rscale = 1;
}
/* Generate code for pointer subtraction */
flags = CF_PTR;
}
/* We can only do constant expressions for: /* We can only do constant expressions for:
** - integer subtraction: ** - integer subtraction:
** - numeric - numeric ** - numeric - numeric
@@ -3266,24 +3280,14 @@ static void parsesub (ExprDesc* Expr)
*/ */
if (IsClassPtr (lhst) && IsClassPtr (rhst)) { if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
/* Pointer diff */ /* Pointer Diff. We've got the scale factor and flags above */
if (TypeCmp (lhst, rhst).C >= TC_STRICT_COMPATIBLE) { typecmp_t Cmp = TypeCmp (lhst, rhst);
/* We'll have to scale the result */ if (Cmp.C < TC_STRICT_COMPATIBLE) {
rscale = PSizeOf (lhst);
/* We cannot scale by 0-size or unknown-size */
if (rscale == 0) {
TypeCompatibilityDiagnostic (lhst, rhst,
1, "Invalid pointer types in subtraction: '%s' and '%s'");
/* Avoid further errors */
rscale = 1;
}
} else {
TypeCompatibilityDiagnostic (lhst, rhst, TypeCompatibilityDiagnostic (lhst, rhst,
1, "Incompatible pointer types in subtraction: '%s' and '%s'"); 1, "Incompatible pointer types in subtraction: '%s' and '%s'");
} }
/* Operate on pointers, result type is an integer */ /* Operate on pointers, result type is an integer */
flags = CF_PTR;
Expr->Type = type_int; Expr->Type = type_int;
/* Check for a constant rhs expression */ /* Check for a constant rhs expression */
@@ -3338,10 +3342,7 @@ static void parsesub (ExprDesc* Expr)
/* Both sides are constant. Check for pointer arithmetic */ /* Both sides are constant. Check for pointer arithmetic */
if (IsClassPtr (lhst) && IsClassInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Pointer subtraction. We've got the scale factor and flags above */
rscale = CheckedPSizeOf (lhst);
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction. We'll adjust the types later */ /* Integer subtraction. We'll adjust the types later */
} else { } else {
@@ -3383,7 +3384,7 @@ static void parsesub (ExprDesc* Expr)
flags = typeadjust (Expr, &Expr2, 1); flags = typeadjust (Expr, &Expr2, 1);
} }
/* Do the subtraction */ /* Do the subtraction */
g_dec (flags | CF_CONST, Expr2.IVal); g_dec (flags | CF_CONST, Expr2.IVal * rscale);
} else { } else {
if (IsClassInt (lhst)) { if (IsClassInt (lhst)) {
/* Adjust the types */ /* Adjust the types */
@@ -3391,6 +3392,7 @@ static void parsesub (ExprDesc* Expr)
} }
/* Load rhs into the primary */ /* Load rhs into the primary */
LoadExpr (CF_NONE, &Expr2); LoadExpr (CF_NONE, &Expr2);
g_scale (TypeOf (rhst), rscale);
/* Generate code for the sub (the & is a hack here) */ /* Generate code for the sub (the & is a hack here) */
g_sub (flags & ~CF_CONST, 0); g_sub (flags & ~CF_CONST, 0);
} }
@@ -3402,10 +3404,7 @@ static void parsesub (ExprDesc* Expr)
/* Left hand side is not constant, right hand side is */ /* Left hand side is not constant, right hand side is */
if (IsClassPtr (lhst) && IsClassInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Pointer subtraction. We've got the scale factor and flags above */
Expr2.IVal *= CheckedPSizeOf (lhst);
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction. We'll adjust the types later */ /* Integer subtraction. We'll adjust the types later */
} else { } else {
@@ -3422,7 +3421,7 @@ static void parsesub (ExprDesc* Expr)
flags = typeadjust (Expr, &Expr2, 1); flags = typeadjust (Expr, &Expr2, 1);
} }
/* Do the subtraction */ /* Do the subtraction */
g_dec (flags | CF_CONST, Expr2.IVal); g_dec (flags | CF_CONST, Expr2.IVal * rscale);
} else { } else {
if (IsClassInt (lhst)) { if (IsClassInt (lhst)) {
/* Adjust the types */ /* Adjust the types */
@@ -3430,6 +3429,7 @@ static void parsesub (ExprDesc* Expr)
} }
/* Load rhs into the primary */ /* Load rhs into the primary */
LoadExpr (CF_NONE, &Expr2); LoadExpr (CF_NONE, &Expr2);
g_scale (TypeOf (rhst), rscale);
/* Generate code for the sub (the & is a hack here) */ /* Generate code for the sub (the & is a hack here) */
g_sub (flags & ~CF_CONST, 0); g_sub (flags & ~CF_CONST, 0);
} }
@@ -3449,9 +3449,7 @@ static void parsesub (ExprDesc* Expr)
/* Check for pointer arithmetic */ /* Check for pointer arithmetic */
if (IsClassPtr (lhst) && IsClassInt (rhst)) { if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */ /* Left is pointer, right is int, must scale rhs */
g_scale (CF_INT, CheckedPSizeOf (lhst)); g_scale (CF_INT, rscale);
/* Operate on pointers, result type is a pointer */
flags = CF_PTR;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) { } else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Adjust operand types */ /* Adjust operand types */
flags = typeadjust (Expr, &Expr2, 0); flags = typeadjust (Expr, &Expr2, 0);