Fixed pointer subtraction in certain very rare cases.
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user