| author | |
| committer | |
| log | 8696e52a3d617ce30ec6202adc89cb10c67bcc43 |
| tree | 6ed5cbd72781165f2831ea3ace5f309689ed4e61 |
| parent | 126f5702df2ac86ced868d9e532db44313144452 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
* Make unary minus for unsigned types a compile error
* Add unreachable when generating unsigned negate3 files changed, 37 insertions(+), 21 deletions(-)
src/codegen.cpp+6-6| ... | @@ -3540,7 +3540,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl | ... | @@ -3540,7 +3540,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutableGen *executabl |
| 3540 | 3540 | ||
| 3541 | for (size_t field_i = 0; field_i < field_count; field_i += 1) { | 3541 | for (size_t field_i = 0; field_i < field_count; field_i += 1) { |
| 3542 | TypeEnumField *type_enum_field = &wanted_type->data.enumeration.fields[field_i]; | 3542 | TypeEnumField *type_enum_field = &wanted_type->data.enumeration.fields[field_i]; |
| 3543 | 3543 | ||
| 3544 | Buf *name = type_enum_field->name; | 3544 | Buf *name = type_enum_field->name; |
| 3545 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, name); | 3545 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, name); |
| 3546 | if (entry != nullptr) { | 3546 | if (entry != nullptr) { |
| ... | @@ -3654,7 +3654,7 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper | ... | @@ -3654,7 +3654,7 @@ static LLVMValueRef ir_gen_negation(CodeGen *g, IrInstGen *inst, IrInstGen *oper |
| 3654 | } else if (scalar_type->data.integral.is_signed) { | 3654 | } else if (scalar_type->data.integral.is_signed) { |
| 3655 | return LLVMBuildNSWNeg(g->builder, llvm_operand, ""); | 3655 | return LLVMBuildNSWNeg(g->builder, llvm_operand, ""); |
| 3656 | } else { | 3656 | } else { |
| 3657 | return LLVMBuildNUWNeg(g->builder, llvm_operand, ""); | 3657 | zig_unreachable(); |
| 3658 | } | 3658 | } |
| 3659 | } else { | 3659 | } else { |
| 3660 | zig_unreachable(); | 3660 | zig_unreachable(); |
| ... | @@ -3984,7 +3984,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable, | ... | @@ -3984,7 +3984,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutableGen *executable, |
| 3984 | assert(array_type->data.pointer.child_type->id == ZigTypeIdArray); | 3984 | assert(array_type->data.pointer.child_type->id == ZigTypeIdArray); |
| 3985 | array_type = array_type->data.pointer.child_type; | 3985 | array_type = array_type->data.pointer.child_type; |
| 3986 | } | 3986 | } |
| 3987 | 3987 | ||
| 3988 | assert(array_type->data.array.len != 0 || array_type->data.array.sentinel != nullptr); | 3988 | assert(array_type->data.array.len != 0 || array_type->data.array.sentinel != nullptr); |
| 3989 | 3989 | ||
| 3990 | if (safety_check_on) { | 3990 | if (safety_check_on) { |
| ... | @@ -5258,7 +5258,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { | ... | @@ -5258,7 +5258,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { |
| 5258 | 5258 | ||
| 5259 | for (size_t field_i = 0; field_i < field_count; field_i += 1) { | 5259 | for (size_t field_i = 0; field_i < field_count; field_i += 1) { |
| 5260 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; | 5260 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i]; |
| 5261 | 5261 | ||
| 5262 | Buf *name = type_enum_field->name; | 5262 | Buf *name = type_enum_field->name; |
| 5263 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, name); | 5263 | auto entry = occupied_tag_values.put_unique(type_enum_field->value, name); |
| 5264 | if (entry != nullptr) { | 5264 | if (entry != nullptr) { |
| ... | @@ -5471,7 +5471,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { | ... | @@ -5471,7 +5471,7 @@ static LLVMTypeRef get_atomic_abi_type(CodeGen *g, IrInstGen *instruction) { |
| 5471 | } | 5471 | } |
| 5472 | auto bit_count = operand_type->data.integral.bit_count; | 5472 | auto bit_count = operand_type->data.integral.bit_count; |
| 5473 | bool is_signed = operand_type->data.integral.is_signed; | 5473 | bool is_signed = operand_type->data.integral.is_signed; |
| 5474 | 5474 | ||
| 5475 | ir_assert(bit_count != 0, instruction); | 5475 | ir_assert(bit_count != 0, instruction); |
| 5476 | if (bit_count == 1 || !is_power_of_2(bit_count)) { | 5476 | if (bit_count == 1 || !is_power_of_2(bit_count)) { |
| 5477 | return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8)); | 5477 | return get_llvm_type(g, get_int_type(g, is_signed, operand_type->abi_size * 8)); |
| ... | @@ -9265,7 +9265,7 @@ static void init(CodeGen *g) { | ... | @@ -9265,7 +9265,7 @@ static void init(CodeGen *g) { |
| 9265 | abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32" : "lp64"; | 9265 | abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32" : "lp64"; |
| 9266 | } | 9266 | } |
| 9267 | } | 9267 | } |
| 9268 | 9268 | ||
| 9269 | g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), | 9269 | g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), |
| 9270 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, | 9270 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, |
| 9271 | to_llvm_code_model(g), g->function_sections, float_abi, abi_name); | 9271 | to_llvm_code_model(g), g->function_sections, float_abi, abi_name); |
src/ir.cpp+22-15| ... | @@ -12602,28 +12602,28 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT | ... | @@ -12602,28 +12602,28 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 12602 | if (prev_type->id == ZigTypeIdPointer && | 12602 | if (prev_type->id == ZigTypeIdPointer && |
| 12603 | prev_type->data.pointer.ptr_len == PtrLenSingle && | 12603 | prev_type->data.pointer.ptr_len == PtrLenSingle && |
| 12604 | prev_type->data.pointer.child_type->id == ZigTypeIdArray && | 12604 | prev_type->data.pointer.child_type->id == ZigTypeIdArray && |
| 12605 | ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown))) | 12605 | ((cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenUnknown))) |
| 12606 | { | 12606 | { |
| 12607 | prev_inst = cur_inst; | 12607 | prev_inst = cur_inst; |
| 12608 | 12608 | ||
| 12609 | if (prev_type->data.pointer.is_const && !cur_type->data.pointer.is_const) { | 12609 | if (prev_type->data.pointer.is_const && !cur_type->data.pointer.is_const) { |
| 12610 | // const array pointer and non-const unknown pointer | 12610 | // const array pointer and non-const unknown pointer |
| 12611 | make_the_pointer_const = true; | 12611 | make_the_pointer_const = true; |
| 12612 | } | 12612 | } |
| 12613 | continue; | 12613 | continue; |
| 12614 | } | 12614 | } |
| 12615 | 12615 | ||
| 12616 | // *[N]T to [*]T | 12616 | // *[N]T to [*]T |
| 12617 | if (cur_type->id == ZigTypeIdPointer && | 12617 | if (cur_type->id == ZigTypeIdPointer && |
| 12618 | cur_type->data.pointer.ptr_len == PtrLenSingle && | 12618 | cur_type->data.pointer.ptr_len == PtrLenSingle && |
| 12619 | cur_type->data.pointer.child_type->id == ZigTypeIdArray && | 12619 | cur_type->data.pointer.child_type->id == ZigTypeIdArray && |
| 12620 | ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown))) | 12620 | ((prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenUnknown))) |
| 12621 | { | 12621 | { |
| 12622 | if (cur_type->data.pointer.is_const && !prev_type->data.pointer.is_const) { | 12622 | if (cur_type->data.pointer.is_const && !prev_type->data.pointer.is_const) { |
| 12623 | // const array pointer and non-const unknown pointer | 12623 | // const array pointer and non-const unknown pointer |
| 12624 | make_the_pointer_const = true; | 12624 | make_the_pointer_const = true; |
| 12625 | } | 12625 | } |
| 12626 | continue; | 12626 | continue; |
| 12627 | } | 12627 | } |
| 12628 | 12628 | ||
| 12629 | // *[N]T to []T | 12629 | // *[N]T to []T |
| ... | @@ -20987,17 +20987,24 @@ static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction | ... | @@ -20987,17 +20987,24 @@ static IrInstGen *ir_analyze_negation(IrAnalyze *ira, IrInstSrcUnOp *instruction |
| 20987 | if (type_is_invalid(expr_type)) | 20987 | if (type_is_invalid(expr_type)) |
| 20988 | return ira->codegen->invalid_inst_gen; | 20988 | return ira->codegen->invalid_inst_gen; |
| 20989 | 20989 | ||
| 20990 | if (!(expr_type->id == ZigTypeIdInt || expr_type->id == ZigTypeIdComptimeInt || | ||
| 20991 | expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat || | ||
| 20992 | expr_type->id == ZigTypeIdVector)) | ||
| 20993 | { | ||
| 20994 | ir_add_error(ira, &instruction->base.base, | ||
| 20995 | buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name))); | ||
| 20996 | return ira->codegen->invalid_inst_gen; | ||
| 20997 | } | ||
| 20998 | |||
| 20999 | bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap); | 20990 | bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap); |
| 21000 | 20991 | ||
| 20992 | switch (expr_type->id) { | ||
| 20993 | case ZigTypeIdComptimeInt: | ||
| 20994 | case ZigTypeIdFloat: | ||
| 20995 | case ZigTypeIdComptimeFloat: | ||
| 20996 | case ZigTypeIdVector: | ||
| 20997 | break; | ||
| 20998 | case ZigTypeIdInt: | ||
| 20999 | if (is_wrap_op || expr_type->data.integral.is_signed) | ||
| 21000 | break; | ||
| 21001 | ZIG_FALLTHROUGH; | ||
| 21002 | default: | ||
| 21003 | ir_add_error(ira, &instruction->base.base, | ||
| 21004 | buf_sprintf("negation of type '%s'", buf_ptr(&expr_type->name))); | ||
| 21005 | return ira->codegen->invalid_inst_gen; | ||
| 21006 | } | ||
| 21007 | |||
| 21001 | ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type; | 21008 | ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type; |
| 21002 | 21009 | ||
| 21003 | if (instr_is_comptime(value)) { | 21010 | if (instr_is_comptime(value)) { |
| ... | @@ -30380,7 +30387,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF | ... | @@ -30380,7 +30387,7 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, IrInst* source_instr, BuiltinF |
| 30380 | case BuiltinFnIdTrunc: | 30387 | case BuiltinFnIdTrunc: |
| 30381 | f128M_trunc(in, out); | 30388 | f128M_trunc(in, out); |
| 30382 | break; | 30389 | break; |
| 30383 | case BuiltinFnIdRound: | 30390 | case BuiltinFnIdRound: |
| 30384 | f128M_roundToInt(in, softfloat_round_near_maxMag, false, out); | 30391 | f128M_roundToInt(in, softfloat_round_near_maxMag, false, out); |
| 30385 | break; | 30392 | break; |
| 30386 | case BuiltinFnIdNearbyInt: | 30393 | case BuiltinFnIdNearbyInt: |
test/compile_errors.zig+9| ... | @@ -7530,4 +7530,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -7530,4 +7530,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 7530 | , &[_][]const u8{ | 7530 | , &[_][]const u8{ |
| 7531 | "tmp.zig:2:9: error: @wasmMemoryGrow is a wasm32 feature only", | 7531 | "tmp.zig:2:9: error: @wasmMemoryGrow is a wasm32 feature only", |
| 7532 | }); | 7532 | }); |
| 7533 | |||
| 7534 | cases.add("Issue #5586: Make unary minus for unsigned types a compile error", | ||
| 7535 | \\export fn f(x: u32) u32 { | ||
| 7536 | \\ const y = -%x; | ||
| 7537 | \\ return -y; | ||
| 7538 | \\} | ||
| 7539 | , &[_][]const u8{ | ||
| 7540 | "tmp.zig:3:12: error: negation of type 'u32'" | ||
| 7541 | }); | ||
| 7533 | } | 7542 | } |