commit 444f9ae789ffc750f98b7ce512e5c3e7c1762f08
parent 251b8ac3485a3ec016a89fd8c78bec021e587f27
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Sat, 27 Aug 2022 13:54:34 +0200
fix error reporting of non-type objects appearing in type contexts
Types that contained aliases sometimes crashed the compiler if their
members were actually not aliases but non-type objects. This is fixed by
adding a check for non-type objects into resolve_dimensions(). A similar
check already exists in the resolve_type() function.
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
2 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -3825,7 +3825,19 @@ resolve_enum_alias(struct context *ctx, const struct scope_object *obj)
const struct scope_object *
resolve_dimensions(struct context *ctx, const struct scope_object *obj)
{
+ assert(obj->otype == O_SCAN);
struct incomplete_declaration *idecl = (struct incomplete_declaration*)obj;
+ if (idecl->type != IDECL_DECL || idecl->decl.decl_type != AST_DECL_TYPE) {
+ struct location loc;
+ if (idecl->type == IDECL_ENUM_FLD) {
+ loc = idecl->field->field->loc;
+ } else {
+ loc = idecl->decl.loc;
+ }
+ error(ctx, loc, false, "'%s' is not a type",
+ identifier_unparse(&idecl->obj.name));
+ handle_errors(ctx->errors);
+ }
struct dimensions dim = type_store_lookup_dimensions(ctx->store,
idecl->decl.type.type);
((struct scope_object *)obj)->type = xcalloc(1, sizeof(struct type));
diff --git a/tests/34-declarations.ha b/tests/34-declarations.ha
@@ -205,18 +205,34 @@ fn sz() void = {
};
fn reject() void = {
- // TODO: figure out a better way to test these
- assert(compile("type a = b; type b = a;") as exited != EXIT_SUCCESS);
- assert(compile("type a = [20]a;") as exited != EXIT_SUCCESS);
- assert(compile("type a = b; type b = a;") as exited != EXIT_SUCCESS);
- assert(compile("type a = [20]a;") as exited != EXIT_SUCCESS);
- assert(compile("type a = unknown;") as exited != EXIT_SUCCESS);
- assert(compile("def x: int = 6; type a = x;") as exited != EXIT_SUCCESS);
- assert(compile("type a = int; type a = str;") as exited != EXIT_SUCCESS);
- assert(compile("def a: int = b; def b: int = a;") as exited != EXIT_SUCCESS);
- assert(compile("def x: size = size(t); type t = [x]int;") as exited != EXIT_SUCCESS);
- assert(compile("def a: int = 12; type t = (int |(...a | a));") as exited != EXIT_SUCCESS);
- assert(compile("def a: int = 12; type t = (int |(...a | a));") as exited != EXIT_SUCCESS);
+ let failures = [
+ "type a = b; type b = a;",
+ "type a = [20]a;",
+ "type a = b; type b = a;",
+ "type a = [20]a;",
+ "type a = unknown;",
+ "def x: int = 6; type a = x;",
+ "type a = int; type a = str;",
+ "def a: int = b; def b: int = a;",
+ "def x: size = size(t); type t = [x]int;",
+ "def a: int = 12; type t = (int |(...a | a));",
+ "type a = (...unknown | int);",
+
+ // usage of non-type aliases
+ "let a: int = 4; type x = a;",
+ "let a: int = 4; type x = *a;",
+ "let a: int = 4; type x = []a;",
+ "let a: int = 4; type x = [3]a;",
+ "let a: int = 4; type x = (str, a);",
+ "let a: int = 4; type x = (str | a);",
+ "let a: int = 4; type x = struct { y: str, z: a};",
+ "let a: int = 4; type x = union { y: str, z: a};",
+ "let a: int = 4; fn x(y: str, z: a) void = { void; };",
+ ];
+
+ for (let i = 0z; i < len(failures); i += 1) {
+ assert(compile(failures[i]) as exited != EXIT_SUCCESS);
+ };
};
// Types t_0 to t_9 form a complete directed graph on 10 vertices.