diff options
| author | Jimmi HC <jhc@liab.dk> | 2018-06-29 10:21:43 +0200 |
|---|---|---|
| committer | Jimmi HC <jhc@liab.dk> | 2018-06-29 10:21:43 +0200 |
| commit | 4c3f27ce1ea17b5236a022971ebace73a02b7c2b (patch) | |
| tree | 9950a381f4803b3124e687bd897451d1a8304b31 /src | |
| parent | b1128b18d5395d85f1c483d8b35e33c57be80722 (diff) | |
| download | zig-4c3f27ce1ea17b5236a022971ebace73a02b7c2b.tar.gz zig-4c3f27ce1ea17b5236a022971ebace73a02b7c2b.zip | |
ir_resolve_const now checks recursivly for undef values
Diffstat (limited to 'src')
| -rw-r--r-- | src/analyze.cpp | 135 | ||||
| -rw-r--r-- | src/analyze.hpp | 1 | ||||
| -rw-r--r-- | src/ir.cpp | 11 |
3 files changed, 145 insertions, 2 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index b3a302a1d4..068ea48c0a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5288,6 +5288,141 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_ return const_val; } +bool contains_comptime_undefined_value(ConstExprValue *value) { + assert(value->special != ConstValSpecialRuntime); + if (value->special == ConstValSpecialUndef) + return true; + + switch (value->type->id) { + case TypeTableEntryIdInvalid: + zig_unreachable(); + + case TypeTableEntryIdPointer: { + ConstPtrValue *ptr = &value->data.x_ptr; + if (ptr->mut == ConstPtrMutRuntimeVar) + return false; + + switch (ptr->special) { + case ConstPtrSpecialInvalid: + zig_unreachable(); + case ConstPtrSpecialRef: + return contains_comptime_undefined_value(ptr->data.ref.pointee); + case ConstPtrSpecialBaseArray: { + size_t index = ptr->data.base_array.elem_index; + ConstExprValue *arr = ptr->data.base_array.array_val; + if (arr->special == ConstValSpecialUndef) + return true; + if (arr->data.x_array.special == ConstArraySpecialUndef) + return true; + + return contains_comptime_undefined_value(&arr->data.x_array.s_none.elements[index]); + } + case ConstPtrSpecialBaseStruct: { + size_t index = ptr->data.base_struct.field_index; + ConstExprValue *str = ptr->data.base_struct.struct_val; + if (str->special == ConstValSpecialUndef) + return true; + + return contains_comptime_undefined_value(&str->data.x_struct.fields[index]); + } + case ConstPtrSpecialFunction: // TODO: Can a fn ptr have an undefined value? + case ConstPtrSpecialDiscard: + case ConstPtrSpecialHardCodedAddr: + return false; + } + } + case TypeTableEntryIdArray: { + ConstArrayValue *arr = &value->data.x_array; + if (arr->special == ConstArraySpecialUndef) + return true; + + for (size_t i = 0; i < value->type->data.array.len; ++i) { + if (contains_comptime_undefined_value(&arr->s_none.elements[i])) + return true; + } + return false; + } + case TypeTableEntryIdStruct: { + ConstStructValue *str = &value->data.x_struct; + if (value->type->data.structure.is_slice) { + ConstExprValue *len = &str->fields[slice_len_index]; + ConstExprValue *ptr = &str->fields[slice_ptr_index]; + if (len->special == ConstValSpecialUndef) + return true; + if (ptr->special == ConstValSpecialUndef) + return true; + + switch (ptr->data.x_ptr.special) { + case ConstPtrSpecialRef: + return contains_comptime_undefined_value(ptr->data.x_ptr.data.ref.pointee); + case ConstPtrSpecialBaseArray: { + size_t offset = ptr->data.x_ptr.data.base_array.elem_index; + ConstExprValue *arr = ptr->data.x_ptr.data.base_array.array_val; + if (arr->special == ConstValSpecialUndef) + return true; + if (arr->data.x_array.special == ConstArraySpecialUndef) + return true; + + uint64_t slice_len = bigint_as_unsigned(&len->data.x_bigint); + for (size_t i = 0; i < slice_len; ++i) { + if (contains_comptime_undefined_value(&arr->data.x_array.s_none.elements[i + offset])) + return true; + } + + return false; + } + case ConstPtrSpecialBaseStruct: + case ConstPtrSpecialInvalid: + case ConstPtrSpecialFunction: + case ConstPtrSpecialDiscard: + case ConstPtrSpecialHardCodedAddr: + zig_unreachable(); + } + } + + for (size_t i = 0; i < value->type->data.structure.src_field_count; ++i) { + if (contains_comptime_undefined_value(&str->fields[i])) + return true; + } + return false; + } + case TypeTableEntryIdOptional: + if (value->data.x_optional == nullptr) + return false; + + return contains_comptime_undefined_value(value->data.x_optional); + case TypeTableEntryIdErrorUnion: + // TODO: Can error union error be undefined? + if (value->data.x_err_union.err != nullptr) + return false; + + return contains_comptime_undefined_value(value->data.x_err_union.payload); + case TypeTableEntryIdUnion: + return contains_comptime_undefined_value(value->data.x_union.payload); + + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdComptimeFloat: + case TypeTableEntryIdComptimeInt: + case TypeTableEntryIdUndefined: + case TypeTableEntryIdNull: + case TypeTableEntryIdErrorSet: + case TypeTableEntryIdEnum: + case TypeTableEntryIdFn: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdMetaType: + case TypeTableEntryIdOpaque: + case TypeTableEntryIdPromise: + return false; + } + zig_unreachable(); +} void init_const_undefined(CodeGen *g, ConstExprValue *const_val) { TypeTableEntry *wanted_type = const_val->type; diff --git a/src/analyze.hpp b/src/analyze.hpp index 88e06b2390..100f85d4d9 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -93,6 +93,7 @@ void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry); void type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry); void complete_enum(CodeGen *g, TypeTableEntry *enum_type); bool ir_get_var_is_comptime(VariableTableEntry *var); +bool contains_comptime_undefined_value(ConstExprValue *value); bool const_values_equal(ConstExprValue *a, ConstExprValue *b); void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max); diff --git a/src/ir.cpp b/src/ir.cpp index c6078e755d..2cce4a5044 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9148,8 +9148,15 @@ enum UndefAllowed { static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { switch (value->value.special) { - case ConstValSpecialStatic: - return &value->value; + case ConstValSpecialStatic: { + ConstExprValue *res = &value->value; + if (undef_allowed == UndefBad && contains_comptime_undefined_value(res)) { + ir_add_error(ira, value, buf_sprintf("use of undefined value")); + return nullptr; + } + + return res; + } case ConstValSpecialRuntime: ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); return nullptr; |
