Commit 4c3f27ce1e
Changed files (4)
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;
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);
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;
test/compile_errors.zig
@@ -4124,4 +4124,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
,
".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic",
);
+
+ cases.add(
+ "Trying to pass undefined array to function taking comptime array by value",
+ \\fn a(comptime b: [2]u8) u8 { return b[0]; }
+ \\
+ \\test "" {
+ \\ const arr: [2]u8 = undefined;
+ \\ _ = a(arr);
+ \\}
+ ,
+ ".tmp_source.zig:5:11: error: use of undefined value",
+ );
+
+
+
}