authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-06-29 10:21:43+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-06-29 10:21:43+02:00
log4c3f27ce1ea17b5236a022971ebace73a02b7c2b
tree9950a381f4803b3124e687bd897451d1a8304b31
parentb1128b18d5395d85f1c483d8b35e33c57be80722

ir_resolve_const now checks recursivly for undef values


4 files changed, 160 insertions(+), 2 deletions(-)

src/analyze.cpp+135
......@@ -5288,6 +5288,141 @@ ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_
52885288 return const_val;
52895289}
52905290
5291bool contains_comptime_undefined_value(ConstExprValue *value) {
5292 assert(value->special != ConstValSpecialRuntime);
5293 if (value->special == ConstValSpecialUndef)
5294 return true;
5295
5296 switch (value->type->id) {
5297 case TypeTableEntryIdInvalid:
5298 zig_unreachable();
5299
5300 case TypeTableEntryIdPointer: {
5301 ConstPtrValue *ptr = &value->data.x_ptr;
5302 if (ptr->mut == ConstPtrMutRuntimeVar)
5303 return false;
5304
5305 switch (ptr->special) {
5306 case ConstPtrSpecialInvalid:
5307 zig_unreachable();
5308 case ConstPtrSpecialRef:
5309 return contains_comptime_undefined_value(ptr->data.ref.pointee);
5310 case ConstPtrSpecialBaseArray: {
5311 size_t index = ptr->data.base_array.elem_index;
5312 ConstExprValue *arr = ptr->data.base_array.array_val;
5313 if (arr->special == ConstValSpecialUndef)
5314 return true;
5315 if (arr->data.x_array.special == ConstArraySpecialUndef)
5316 return true;
5317
5318 return contains_comptime_undefined_value(&arr->data.x_array.s_none.elements[index]);
5319 }
5320 case ConstPtrSpecialBaseStruct: {
5321 size_t index = ptr->data.base_struct.field_index;
5322 ConstExprValue *str = ptr->data.base_struct.struct_val;
5323 if (str->special == ConstValSpecialUndef)
5324 return true;
5325
5326 return contains_comptime_undefined_value(&str->data.x_struct.fields[index]);
5327 }
5328 case ConstPtrSpecialFunction: // TODO: Can a fn ptr have an undefined value?
5329 case ConstPtrSpecialDiscard:
5330 case ConstPtrSpecialHardCodedAddr:
5331 return false;
5332 }
5333 }
5334 case TypeTableEntryIdArray: {
5335 ConstArrayValue *arr = &value->data.x_array;
5336 if (arr->special == ConstArraySpecialUndef)
5337 return true;
5338
5339 for (size_t i = 0; i < value->type->data.array.len; ++i) {
5340 if (contains_comptime_undefined_value(&arr->s_none.elements[i]))
5341 return true;
5342 }
5343 return false;
5344 }
5345 case TypeTableEntryIdStruct: {
5346 ConstStructValue *str = &value->data.x_struct;
5347 if (value->type->data.structure.is_slice) {
5348 ConstExprValue *len = &str->fields[slice_len_index];
5349 ConstExprValue *ptr = &str->fields[slice_ptr_index];
5350 if (len->special == ConstValSpecialUndef)
5351 return true;
5352 if (ptr->special == ConstValSpecialUndef)
5353 return true;
5354
5355 switch (ptr->data.x_ptr.special) {
5356 case ConstPtrSpecialRef:
5357 return contains_comptime_undefined_value(ptr->data.x_ptr.data.ref.pointee);
5358 case ConstPtrSpecialBaseArray: {
5359 size_t offset = ptr->data.x_ptr.data.base_array.elem_index;
5360 ConstExprValue *arr = ptr->data.x_ptr.data.base_array.array_val;
5361 if (arr->special == ConstValSpecialUndef)
5362 return true;
5363 if (arr->data.x_array.special == ConstArraySpecialUndef)
5364 return true;
5365
5366 uint64_t slice_len = bigint_as_unsigned(&len->data.x_bigint);
5367 for (size_t i = 0; i < slice_len; ++i) {
5368 if (contains_comptime_undefined_value(&arr->data.x_array.s_none.elements[i + offset]))
5369 return true;
5370 }
5371
5372 return false;
5373 }
5374 case ConstPtrSpecialBaseStruct:
5375 case ConstPtrSpecialInvalid:
5376 case ConstPtrSpecialFunction:
5377 case ConstPtrSpecialDiscard:
5378 case ConstPtrSpecialHardCodedAddr:
5379 zig_unreachable();
5380 }
5381 }
5382
5383 for (size_t i = 0; i < value->type->data.structure.src_field_count; ++i) {
5384 if (contains_comptime_undefined_value(&str->fields[i]))
5385 return true;
5386 }
5387 return false;
5388 }
5389 case TypeTableEntryIdOptional:
5390 if (value->data.x_optional == nullptr)
5391 return false;
5392
5393 return contains_comptime_undefined_value(value->data.x_optional);
5394 case TypeTableEntryIdErrorUnion:
5395 // TODO: Can error union error be undefined?
5396 if (value->data.x_err_union.err != nullptr)
5397 return false;
5398
5399 return contains_comptime_undefined_value(value->data.x_err_union.payload);
5400 case TypeTableEntryIdUnion:
5401 return contains_comptime_undefined_value(value->data.x_union.payload);
5402
5403 case TypeTableEntryIdArgTuple:
5404 case TypeTableEntryIdVoid:
5405 case TypeTableEntryIdBool:
5406 case TypeTableEntryIdUnreachable:
5407 case TypeTableEntryIdInt:
5408 case TypeTableEntryIdFloat:
5409 case TypeTableEntryIdComptimeFloat:
5410 case TypeTableEntryIdComptimeInt:
5411 case TypeTableEntryIdUndefined:
5412 case TypeTableEntryIdNull:
5413 case TypeTableEntryIdErrorSet:
5414 case TypeTableEntryIdEnum:
5415 case TypeTableEntryIdFn:
5416 case TypeTableEntryIdNamespace:
5417 case TypeTableEntryIdBlock:
5418 case TypeTableEntryIdBoundFn:
5419 case TypeTableEntryIdMetaType:
5420 case TypeTableEntryIdOpaque:
5421 case TypeTableEntryIdPromise:
5422 return false;
5423 }
5424 zig_unreachable();
5425}
52915426
52925427void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
52935428 TypeTableEntry *wanted_type = const_val->type;
src/analyze.hpp+1
......@@ -93,6 +93,7 @@ void ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
9393void type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry);
9494void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
9595bool ir_get_var_is_comptime(VariableTableEntry *var);
96bool contains_comptime_undefined_value(ConstExprValue *value);
9697bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
9798void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
9899void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
src/ir.cpp+9-2
......@@ -9148,8 +9148,15 @@ enum UndefAllowed {
91489148
91499149static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
91509150 switch (value->value.special) {
9151 case ConstValSpecialStatic:
9152 return &value->value;
9151 case ConstValSpecialStatic: {
9152 ConstExprValue *res = &value->value;
9153 if (undef_allowed == UndefBad && contains_comptime_undefined_value(res)) {
9154 ir_add_error(ira, value, buf_sprintf("use of undefined value"));
9155 return nullptr;
9156 }
9157
9158 return res;
9159 }
91539160 case ConstValSpecialRuntime:
91549161 ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression"));
91559162 return nullptr;
test/compile_errors.zig+15
......@@ -4124,4 +4124,19 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
41244124 ,
41254125 ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic",
41264126 );
4127
4128 cases.add(
4129 "Trying to pass undefined array to function taking comptime array by value",
4130 \\fn a(comptime b: [2]u8) u8 { return b[0]; }
4131 \\
4132 \\test "" {
4133 \\ const arr: [2]u8 = undefined;
4134 \\ _ = a(arr);
4135 \\}
4136 ,
4137 ".tmp_source.zig:5:11: error: use of undefined value",
4138 );
4139
4140
4141
41274142}