diff --git a/releasenotes.md b/releasenotes.md index 71f08767d..c06363dd9 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -99,6 +99,7 @@ - When a global const has invalid attributes, handling is incorrect, leading to a crash #2785. - `int? ?` was not correctly handled. #2786 - Casting const bytes to vector with different element size was broken #2787 +- Unable to access fields of a const inline enum with an aggregate underlying type. #2802 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index e0e03f48c..a56efc18a 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -251,6 +251,14 @@ Expr *sema_enter_inline_member(Expr *parent, CanonicalType *type) expr->type = type; break; } + case TYPE_CONST_ENUM: + { + Decl *decl = type->decl; + if (!decl->is_substruct) return NULL; + expr = expr_copy(parent); + expr->type = decl->enums.type_info->type; + return expr; + } case TYPE_ENUM: { Decl *decl = type->decl; diff --git a/test/test_suite/enumerations/const_enum_inline_member.c3t b/test/test_suite/enumerations/const_enum_inline_member.c3t new file mode 100644 index 000000000..0115fe8d6 --- /dev/null +++ b/test/test_suite/enumerations/const_enum_inline_member.c3t @@ -0,0 +1,36 @@ +// #target: macos-x64 +module test; +struct Bar +{ + uint x, y, z; +} + +enum Foo : const inline Bar +{ + X = {1, 0, 0}, + Y = {0, 1, 0}, + Z = {0, 0, 1}, +} + +fn int main() +{ + uint a = Foo.X.x; + Foo b = X; + uint c = b.y; + return 0; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %a = alloca i32, align 4 + %b = alloca %Bar, align 4 + %c = alloca i32, align 4 + store i32 1, ptr %a, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 4 @.__const, i32 12, i1 false) + %ptradd = getelementptr inbounds i8, ptr %b, i64 4 + %0 = load i32, ptr %ptradd, align 4 + store i32 %0, ptr %c, align 4 + ret i32 0 +}