mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-20 18:52:28 +00:00
[qfcc] Correctly implement pointer arithmetic
This commit is contained in:
parent
c5400c4581
commit
441e7b99bc
1 changed files with 56 additions and 18 deletions
|
@ -46,6 +46,7 @@ typedef struct {
|
|||
} expr_type_t;
|
||||
|
||||
static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2);
|
||||
static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2);
|
||||
static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2);
|
||||
static expr_t *double_compare (int op, expr_t *e1, expr_t *e2);
|
||||
|
||||
|
@ -176,13 +177,13 @@ static expr_type_t func_func[] = {
|
|||
};
|
||||
|
||||
static expr_type_t pointer_pointer[] = {
|
||||
{'-', &type_integer, &type_integer, &type_integer},
|
||||
{EQ, &type_integer},
|
||||
{NE, &type_integer},
|
||||
{LE, &type_integer},
|
||||
{GE, &type_integer},
|
||||
{LT, &type_integer},
|
||||
{GT, &type_integer},
|
||||
{'-', 0, 0, 0, pointer_arithmetic},
|
||||
{EQ, 0, 0, 0, pointer_compare},
|
||||
{NE, 0, 0, 0, pointer_compare},
|
||||
{LE, 0, 0, 0, pointer_compare},
|
||||
{GE, 0, 0, 0, pointer_compare},
|
||||
{LT, 0, 0, 0, pointer_compare},
|
||||
{GT, 0, 0, 0, pointer_compare},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
@ -255,7 +256,7 @@ static expr_type_t integer_vector[] = {
|
|||
};
|
||||
|
||||
static expr_type_t integer_pointer[] = {
|
||||
{'+', &type_pointer, 0, &type_integer},
|
||||
{'+', 0, 0, 0, pointer_arithmetic},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
@ -735,21 +736,58 @@ static expr_t *
|
|||
pointer_arithmetic (int op, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
expr_t *e;
|
||||
type_t *ptype = get_type (e1);
|
||||
type_t *t1 = get_type (e1);
|
||||
type_t *t2 = get_type (e2);
|
||||
expr_t *ptr;
|
||||
expr_t *offset;
|
||||
expr_t *psize;
|
||||
type_t *ptype;
|
||||
|
||||
if (!is_pointer (ptype)) {
|
||||
ptype = get_type (e2);
|
||||
}
|
||||
if (!is_pointer (ptype)) {
|
||||
if (!is_pointer (t1) && !is_pointer (t2)) {
|
||||
internal_error (e1, "pointer arithmetic on non-pointers");
|
||||
}
|
||||
|
||||
e1 = cast_expr (&type_integer, e1);
|
||||
e2 = cast_expr (&type_integer, e2);
|
||||
e = binary_expr (op, e1, e2);
|
||||
if (is_pointer (t1) && is_pointer (t2)) {
|
||||
if (op != '-') {
|
||||
return error (e2, "invalid pointer operation");
|
||||
}
|
||||
if (t1 != t2) {
|
||||
return error (e2, "cannot use %c on pointers of different types",
|
||||
op);
|
||||
}
|
||||
e1 = cast_expr (&type_integer, e1);
|
||||
e2 = cast_expr (&type_integer, e2);
|
||||
psize = new_integer_expr (type_size (t1->t.fldptr.type));
|
||||
return binary_expr ('/', binary_expr ('-', e1, e2), psize);
|
||||
} else if (is_pointer (t1)) {
|
||||
offset = cast_expr (&type_integer, e2);
|
||||
ptr = cast_expr (&type_integer, e1);
|
||||
ptype = t1;
|
||||
} else if (is_pointer (t2)) {
|
||||
offset = cast_expr (&type_integer, e1);
|
||||
ptr = cast_expr (&type_integer, e2);
|
||||
ptype = t2;
|
||||
}
|
||||
psize = new_integer_expr (type_size (ptype->t.fldptr.type));
|
||||
e = binary_expr (op, ptr, binary_expr ('*', offset, psize));
|
||||
return cast_expr (ptype, e);
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
pointer_compare (int op, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
type_t *t1 = get_type (e1);
|
||||
type_t *t2 = get_type (e2);
|
||||
expr_t *e;
|
||||
|
||||
if (!type_assignable (t1, t2)) {
|
||||
return error (e2, "cannot use %s on pointers of different types",
|
||||
get_op_string (op));
|
||||
}
|
||||
e = new_binary_expr (op, e1, e2);
|
||||
e->e.expr.type = &type_integer;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
inverse_multiply (int op, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
|
@ -790,7 +828,7 @@ double_compare (int op, expr_t *e1, expr_t *e2)
|
|||
e1 = cast_expr (&type_double, e1);
|
||||
}
|
||||
e = new_binary_expr (op, e1, e2);
|
||||
e->e.expr.type = &type_double;
|
||||
e->e.expr.type = &type_integer;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue