harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

commit aa264f4772e86d3ff49e89a3887fe24e8c399b8d
parent ca6ac4e270a1902b6b0275e112bc0f549c0f9f66
Author: Sebastian <sebastian@sebsite.pw>
Date:   Thu,  5 Jan 2023 18:05:10 -0500

check: more strict rules for type asserting nullable pointers

The compiler used to not check what the target type of the type
assertion of a nullable pointer was. Because of this, given x is a
nullable *int, expressions like `x as *size` and `x as nullable *int`
were incorrectly allowed. Furthermore, expressions like `x as int` and
`x as size` resulted in an abort() in gen.c.

This has been corrected in accordance with the spec, so now nullable
pointers may be type asserted to null or to a non-nullable pointer type
with the same referent type (i.e. x can now only be type asserted to
null and *int).

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Msrc/check.c | 9+++++++++
Mtests/03-pointers.ha | 14+++++++++++++-
2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/src/check.c b/src/check.c @@ -1447,6 +1447,15 @@ check_expr_cast(struct context *ctx, "a nullable pointer"); return; } + if (secondary->storage != STORAGE_NULL + && (secondary->storage != STORAGE_POINTER + || primary->pointer.referent + != secondary->pointer.referent + || (secondary->pointer.flags & PTR_NULLABLE))) { + error(ctx, aexpr->cast.type->loc, expr, + "Can only type assert nullable pointer into non-nullable pointer of the same type or null"); + return; + } break; } if (primary->storage != STORAGE_TAGGED) { diff --git a/tests/03-pointers.ha b/tests/03-pointers.ha @@ -44,7 +44,7 @@ fn casts() void = { assert((a as null): nullable *void == null); let a: nullable *int = &4; - a as nullable *int; + assert(a is *int); }; fn reject() void = { @@ -101,6 +101,18 @@ fn reject() void = { let a = null; }; ") as exited != EXIT_SUCCESS); + assert(compile(" + fn test() void = { + let a: nullable *int = &4; + a as int; + }; + ") as exited != EXIT_SUCCESS); + assert(compile(" + fn test() void = { + let a: nullable *int = &4; + a as *str; + }; + ") as exited != EXIT_SUCCESS); // type assertions on non-nullable pointers are prohibited assert(compile("