harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/check.c | 32+++++++++++++++++++++++++-------
Msrc/gen.c | 2+-
Msrc/types.c | 3+++
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) {