diff options
| author | Michael Dusan <michael.dusan@gmail.com> | 2020-04-03 11:41:55 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-04-03 19:05:30 -0400 |
| commit | db4c06ce606dcfe989b5c1f76d5ed00e90d5dd9f (patch) | |
| tree | 9feedf90f8670da85296ca253c7f79053a87c839 /src/ir.cpp | |
| parent | f1425fd9da1b2e1297a36108b12b0bd89398b057 (diff) | |
| download | zig-db4c06ce606dcfe989b5c1f76d5ed00e90d5dd9f.tar.gz zig-db4c06ce606dcfe989b5c1f76d5ed00e90d5dd9f.zip | |
stage1: add compile errors for sentinel slicing
closes #3963
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 108 |
1 files changed, 107 insertions, 1 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 2f9e3638f8..1e3fe67b2b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -26583,7 +26583,6 @@ done_with_return_type: if (parent_ptr == nullptr) return ira->codegen->invalid_inst_gen; - if (parent_ptr->special == ConstValSpecialUndef) { array_val = nullptr; abs_offset = 0; @@ -26746,6 +26745,113 @@ done_with_return_type: return ira->codegen->invalid_inst_gen; } + // check sentinel when target is comptime-known + { + if (!sentinel_val) + goto exit_check_sentinel; + + switch (ptr_ptr->value->data.x_ptr.mut) { + case ConstPtrMutComptimeConst: + case ConstPtrMutComptimeVar: + break; + case ConstPtrMutRuntimeVar: + case ConstPtrMutInfer: + goto exit_check_sentinel; + } + + // prepare check parameters + ZigValue *target = const_ptr_pointee(ira, ira->codegen, ptr_ptr->value, instruction->base.base.source_node); + if (target == nullptr) + return ira->codegen->invalid_inst_gen; + + uint64_t target_len = 0; + ZigValue *target_sentinel = nullptr; + ZigValue *target_elements = nullptr; + + for (;;) { + if (target->type->id == ZigTypeIdArray) { + // handle `[N]T` + target_len = target->type->data.array.len; + target_sentinel = target->type->data.array.sentinel; + target_elements = target->data.x_array.data.s_none.elements; + break; + } else if (target->type->id == ZigTypeIdPointer && target->type->data.pointer.child_type->id == ZigTypeIdArray) { + // handle `*[N]T` + target = const_ptr_pointee(ira, ira->codegen, target, instruction->base.base.source_node); + if (target == nullptr) + return ira->codegen->invalid_inst_gen; + assert(target->type->id == ZigTypeIdArray); + continue; + } else if (target->type->id == ZigTypeIdPointer) { + // handle `[*]T` + // handle `[*c]T` + switch (target->data.x_ptr.special) { + case ConstPtrSpecialInvalid: + case ConstPtrSpecialDiscard: + zig_unreachable(); + case ConstPtrSpecialRef: + target = target->data.x_ptr.data.ref.pointee; + assert(target->type->id == ZigTypeIdArray); + continue; + case ConstPtrSpecialBaseArray: + case ConstPtrSpecialSubArray: + target = target->data.x_ptr.data.base_array.array_val; + assert(target->type->id == ZigTypeIdArray); + continue; + case ConstPtrSpecialBaseStruct: + zig_panic("TODO slice const inner struct"); + case ConstPtrSpecialBaseErrorUnionCode: + zig_panic("TODO slice const inner error union code"); + case ConstPtrSpecialBaseErrorUnionPayload: + zig_panic("TODO slice const inner error union payload"); + case ConstPtrSpecialBaseOptionalPayload: + zig_panic("TODO slice const inner optional payload"); + case ConstPtrSpecialHardCodedAddr: + // skip check + goto exit_check_sentinel; + case ConstPtrSpecialFunction: + zig_panic("TODO slice of ptr cast from function"); + case ConstPtrSpecialNull: + zig_panic("TODO slice of null ptr"); + } + break; + } else if (is_slice(target->type)) { + // handle `[]T` + target = target->data.x_struct.fields[slice_ptr_index]; + assert(target->type->id == ZigTypeIdPointer); + continue; + } + + zig_unreachable(); + } + + // perform check + if (target_sentinel == nullptr) { + if (end_scalar >= target_len) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel is out of bounds")); + return ira->codegen->invalid_inst_gen; + } + if (!const_values_equal(ira->codegen, sentinel_val, &target_elements[end_scalar])) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel does not match memory at target index")); + return ira->codegen->invalid_inst_gen; + } + } else { + assert(end_scalar <= target_len); + if (end_scalar == target_len) { + if (!const_values_equal(ira->codegen, sentinel_val, target_sentinel)) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel does not match target-sentinel")); + return ira->codegen->invalid_inst_gen; + } + } else { + if (!const_values_equal(ira->codegen, sentinel_val, &target_elements[end_scalar])) { + ir_add_error(ira, &instruction->base.base, buf_sprintf("slice-sentinel does not match memory at target index")); + return ira->codegen->invalid_inst_gen; + } + } + } + } + exit_check_sentinel: + IrInstGen *result = ir_const(ira, &instruction->base.base, return_type); ZigValue *ptr_val; |
