zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 2a25398c869fcdefe8b6508974a5c463ca833520 (tree)
parent 86397a532ec3c6699c39c8eeb966cd56b66c6c96
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Sun, 24 Dec 2017 04:10:26 -0500

fix segfault when passing union enum with sub byte...

...field to const slice parameter

we use a packed struct internally to represent a const array
of disparate union values, and needed to update the internal
getelementptr instruction to recognize that.

closes #664

Diffstat:
Msrc/codegen.cpp | 26+++++++++++++++++++-------
Mstd/debug/index.zig | 2+-
Mtest/cases/union.zig | 15+++++++++++++++
3 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -3705,12 +3705,24 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar ConstParent *parent = &array_const_val->data.x_array.s_none.parent; LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); - TypeTableEntry *usize = g->builtin_types.entry_usize; - LLVMValueRef indices[] = { - LLVMConstNull(usize->type_ref), - LLVMConstInt(usize->type_ref, index, false), - }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); + if (el_type == LLVMArrayTypeKind) { + TypeTableEntry *usize = g->builtin_types.entry_usize; + LLVMValueRef indices[] = { + LLVMConstNull(usize->type_ref), + LLVMConstInt(usize->type_ref, index, false), + }; + return LLVMConstInBoundsGEP(base_ptr, indices, 2); + } else if (el_type == LLVMStructTypeKind) { + TypeTableEntry *u32 = g->builtin_types.entry_u32; + LLVMValueRef indices[] = { + LLVMConstNull(u32->type_ref), + LLVMConstInt(u32->type_ref, index, false), + }; + return LLVMConstInBoundsGEP(base_ptr, indices, 2); + } else { + zig_unreachable(); + } } static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) { @@ -3732,7 +3744,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un TypeTableEntry *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, 0, false), + LLVMConstInt(u32->type_ref, 0, false), // TODO test const union with more aligned tag type than payload }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } diff --git a/std/debug/index.zig b/std/debug/index.zig @@ -8,7 +8,7 @@ const DW = std.dwarf; const ArrayList = std.ArrayList; const builtin = @import("builtin"); -pub use @import("./failing_allocator.zig"); +pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; error MissingDebugInfo; error InvalidDebugInfo; diff --git a/test/cases/union.zig b/test/cases/union.zig @@ -220,3 +220,18 @@ fn assertIsTheUnion2Item1(value: &const TheUnion2) { assert(*value == TheUnion2.Item1); } + +pub const PackThis = union(enum) { + Invalid: bool, + StringLiteral: u2, +}; + +test "constant packed union" { + testConstPackedUnion([]PackThis { + PackThis { .StringLiteral = 1 }, + }); +} + +fn testConstPackedUnion(expected_tokens: []const PackThis) { + assert(expected_tokens[0].StringLiteral == 1); +}