harec

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

commit e74d1aa3d691b0606c4cd5afd650dd5f1a563867
parent d82683473da59e1cbf6a095ec68db6cfca92f4b1
Author: Ember Sawady <ecs@d2evs.net>
Date:   Thu, 16 Feb 2023 04:11:22 +0000

promote_const: fix ambiguous tagged unions

Specifically fix a crash on ambiguous tagged unions nested inside an
otherwise-unambiguous union where the ambiguous union has the highest
type ID of the members of the unambiguous union and the default type for
the constant isn't assignable to the unambiguous union. In this case,
the recursive promote_const goes through the lower_const(b, NULL)
codepath, so we need to make sure to re-lower b to the tag.

If the tag is NULL, this leads to b incorrectly being lowered to its
default type. However, in this case, either b will get re-lowered and
the temporary lowering to the default type doesn't matter or it won't
and promote_const will return NULL anyways, so we'll error out before
that matters.

Signed-off-by: Ember Sawady <ecs@d2evs.net>

Diffstat:
Msrc/types.c | 1+
Mtests/26-regression.ha | 3+++
2 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/src/types.c b/src/types.c @@ -651,6 +651,7 @@ promote_const(const struct type *a, const struct type *b) { &type_dealias(a)->tagged; tu; tu = tu->next) { const struct type *p = promote_const(tu->type, b); if (!p) { + lower_const(b, tag); continue; } if (tag) { diff --git a/tests/26-regression.ha b/tests/26-regression.ha @@ -21,6 +21,8 @@ def THING: thing = thing{ let global: int = 0; +type mod::t = (size | const size); // needs to have a type id larger than size + export fn main() void = { let t = thing { offs = 0, @@ -116,4 +118,5 @@ export fn main() void = { assert(rt::compile("let a = [*&0];") as rt::exited != rt::EXIT_SUCCESS); assert(rt::compile("fn a() *void = alloc(void);") as rt::exited != rt::EXIT_SUCCESS); assert(rt::compile("fn a() void = { static let b = x & struct { a: int = 0 }; };") as rt::exited != rt::EXIT_SUCCESS); + let a: (size | mod::t) = 0; };