commit 9289e58122286cd48c764a294851c5695ead21e2
parent a2429ed9053bf5e78aa7dbd707abaf092f4252d4
Author: Eyal Sawady <ecs@d2evs.net>
Date: Sat, 4 Sep 2021 07:32:20 +0000
check: don't dealias result type for slice[...]
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -171,6 +171,7 @@ check_expr_access(struct context *ctx,
"Cannot dereference nullable pointer for indexing");
return;
}
+ atype = type_dealias(atype);
const struct type *itype =
type_dealias(expr->access.index->result);
if (atype->storage != STORAGE_ARRAY
@@ -201,6 +202,7 @@ check_expr_access(struct context *ctx,
"Cannot dereference nullable pointer for field selection");
return;
}
+ stype = type_dealias(stype);
if (stype->storage != STORAGE_STRUCT
&& stype->storage != STORAGE_UNION) {
error(ctx, aexpr->access._struct->loc, expr,
@@ -229,6 +231,7 @@ check_expr_access(struct context *ctx,
"Cannot dereference nullable pointer for value selection");
return;
}
+ ttype = type_dealias(ttype);
if (ttype->storage != STORAGE_TUPLE) {
error(ctx, aexpr->access.tuple->loc, expr,
"Cannot select value from non-tuple object");
@@ -351,6 +354,7 @@ check_expr_append(struct context *ctx,
"Cannot dereference nullable pointer for append");
return;
}
+ stype = type_dealias(stype);
if (stype->storage != STORAGE_SLICE) {
error(ctx, aexpr->append.expr->loc, expr,
"append must operate on a slice");
@@ -971,6 +975,7 @@ check_expr_call(struct context *ctx,
"Cannot dereference nullable pointer type for function call");
return;
}
+ fntype = type_dealias(fntype);
if (fntype->storage != STORAGE_FUNCTION) {
error(ctx, aexpr->loc, expr,
"Cannot call non-function type");
@@ -1708,6 +1713,7 @@ check_expr_insert(struct context *ctx,
"Cannot dereference nullable pointer for insert");
return;
}
+ sltype = type_dealias(sltype);
if (sltype->storage != STORAGE_SLICE) {
error(ctx, aexpr->insert.expr->loc, expr,
"cannot insert into non-slice type %s",
@@ -1900,8 +1906,14 @@ check_expr_measure(struct context *ctx,
case M_LEN:
expr->measure.value = xcalloc(1, sizeof(struct expression));
check_expression(ctx, aexpr->measure.value, expr->measure.value, NULL);
- enum type_storage vstor =
- type_dereference(expr->measure.value->result)->storage;
+ const struct type *atype =
+ type_dereference(expr->measure.value->result);
+ if (!atype) {
+ error(ctx, aexpr->access.array->loc, expr,
+ "Cannot dereference nullable pointer for len");
+ return;
+ }
+ enum type_storage vstor = type_dealias(atype)->storage;
bool valid = vstor == STORAGE_ARRAY || vstor == STORAGE_SLICE
|| vstor == STORAGE_STRING;
if (!valid) {
@@ -2158,8 +2170,9 @@ check_expr_slice(struct context *ctx,
"Cannot dereference nullable pointer for slicing");
return;
}
- if (atype->storage != STORAGE_SLICE
- && atype->storage != STORAGE_ARRAY) {
+ const struct type *dtype = type_dealias(atype);
+ if (dtype->storage != STORAGE_SLICE
+ && dtype->storage != STORAGE_ARRAY) {
error(ctx, aexpr->slice.object->loc, expr,
"Cannot slice non-array, non-slice object");
return;
@@ -2192,14 +2205,19 @@ check_expr_slice(struct context *ctx,
}
expr->slice.end = lower_implicit_cast(
&builtin_type_size, expr->slice.end);
- } else if (atype->storage == STORAGE_ARRAY
- && atype->array.length == SIZE_UNDEFINED) {
+ } else if (dtype->storage == STORAGE_ARRAY
+ && dtype->array.length == SIZE_UNDEFINED) {
error(ctx, aexpr->loc, expr,
"Must have end index on array of undefined length");
return;
}
- expr->result = type_store_lookup_slice(ctx->store, atype->array.members);
+ if (dtype->storage == STORAGE_SLICE) {
+ expr->result = atype;
+ } else {
+ expr->result = type_store_lookup_slice(ctx->store,
+ dtype->array.members);
+ }
}
static void
diff --git a/src/gen.c b/src/gen.c
@@ -2200,7 +2200,7 @@ gen_expr_measure(struct gen_context *ctx, const struct expression *expr)
const struct expression *value = expr->measure.value;
switch (expr->measure.op) {
case M_LEN:
- type = type_dereference(value->result);
+ type = type_dealias(type_dereference(value->result));
switch (type->storage) {
case STORAGE_ARRAY:
len = type->array.length;
diff --git a/src/types.c b/src/types.c
@@ -10,6 +10,9 @@ type_dereference(const struct type *type)
{
switch (type->storage) {
case STORAGE_ALIAS:
+ if (type_dealias(type)->storage != STORAGE_POINTER) {
+ return type;
+ }
return type_dereference(type_dealias(type));
case STORAGE_POINTER:
if (type->pointer.flags & PTR_NULLABLE) {