From 07e47c058c480914d45ec0b1f9c61b76f59e6299 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 6 Mar 2018 16:37:03 -0500 Subject: [PATCH] ptrCast builtin now gives an error for removing const qualifier closes #384 --- src/analyze.cpp | 13 +++++++++++++ src/analyze.hpp | 1 + src/ir.cpp | 5 +++++ std/buf_map.zig | 4 +--- std/buf_set.zig | 4 +--- std/os/index.zig | 2 +- std/special/compiler_rt/udivmod.zig | 4 ++-- test/cases/cast.zig | 2 +- test/cases/misc.zig | 2 +- test/compile_errors.zig | 8 ++++++++ 10 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 1e16a8dbd1..fb7f04d6d2 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3753,6 +3753,19 @@ uint32_t get_ptr_align(TypeTableEntry *type) { } } +bool get_ptr_const(TypeTableEntry *type) { + TypeTableEntry *ptr_type = get_codegen_ptr_type(type); + if (ptr_type->id == TypeTableEntryIdPointer) { + return ptr_type->data.pointer.is_const; + } else if (ptr_type->id == TypeTableEntryIdFn) { + return true; + } else if (ptr_type->id == TypeTableEntryIdPromise) { + return true; + } else { + zig_unreachable(); + } +} + AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) { if (fn_entry->param_source_nodes) return fn_entry->param_source_nodes[index]; diff --git a/src/analyze.hpp b/src/analyze.hpp index e9f89aa638..9ed24f4e46 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -55,6 +55,7 @@ bool type_is_codegen_pointer(TypeTableEntry *type); TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type); uint32_t get_ptr_align(TypeTableEntry *type); +bool get_ptr_const(TypeTableEntry *type); TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry); TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); bool type_is_complete(TypeTableEntry *type_entry); diff --git a/src/ir.cpp b/src/ir.cpp index 3d1926298d..251c55df4f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16816,6 +16816,11 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc return ira->codegen->builtin_types.entry_invalid; } + if (get_ptr_const(src_type) && !get_ptr_const(dest_type)) { + ir_add_error(ira, &instruction->base, buf_sprintf("cast discards const qualifier")); + return ira->codegen->builtin_types.entry_invalid; + } + if (instr_is_comptime(ptr)) { ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk); if (!val) diff --git a/std/buf_map.zig b/std/buf_map.zig index d7f81cf2cc..a58df4b2db 100644 --- a/std/buf_map.zig +++ b/std/buf_map.zig @@ -62,9 +62,7 @@ pub const BufMap = struct { } fn free(self: &BufMap, value: []const u8) void { - // remove the const - const mut_value = @ptrCast(&u8, value.ptr)[0..value.len]; - self.hash_map.allocator.free(mut_value); + self.hash_map.allocator.free(value); } fn copy(self: &BufMap, value: []const u8) ![]const u8 { diff --git a/std/buf_set.zig b/std/buf_set.zig index 4fa16762b6..618b985c41 100644 --- a/std/buf_set.zig +++ b/std/buf_set.zig @@ -50,9 +50,7 @@ pub const BufSet = struct { } fn free(self: &BufSet, value: []const u8) void { - // remove the const - const mut_value = @ptrCast(&u8, value.ptr)[0..value.len]; - self.hash_map.allocator.free(mut_value); + self.hash_map.allocator.free(value); } fn copy(self: &BufSet, value: []const u8) ![]const u8 { diff --git a/std/os/index.zig b/std/os/index.zig index 7e9a12c62b..7feaae0ff1 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -1634,7 +1634,7 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { for (args_alloc) |arg| { total_bytes += @sizeOf([]u8) + arg.len; } - const unaligned_allocated_buf = @ptrCast(&u8, args_alloc.ptr)[0..total_bytes]; + const unaligned_allocated_buf = @ptrCast(&const u8, args_alloc.ptr)[0..total_bytes]; const aligned_allocated_buf = @alignCast(@alignOf([]u8), unaligned_allocated_buf); return allocator.free(aligned_allocated_buf); } diff --git a/std/special/compiler_rt/udivmod.zig b/std/special/compiler_rt/udivmod.zig index 82751d5993..07eaef583c 100644 --- a/std/special/compiler_rt/udivmod.zig +++ b/std/special/compiler_rt/udivmod.zig @@ -11,8 +11,8 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); const Log2SingleInt = @import("../../math/index.zig").Log2Int(SingleInt); - const n = *@ptrCast(&[2]SingleInt, &a); // TODO issue #421 - const d = *@ptrCast(&[2]SingleInt, &b); // TODO issue #421 + const n = *@ptrCast(&const [2]SingleInt, &a); // TODO issue #421 + const d = *@ptrCast(&const [2]SingleInt, &b); // TODO issue #421 var q: [2]SingleInt = undefined; var r: [2]SingleInt = undefined; var sr: c_uint = undefined; diff --git a/test/cases/cast.zig b/test/cases/cast.zig index d2671680c8..024ece0055 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -16,7 +16,7 @@ test "integer literal to pointer cast" { test "pointer reinterpret const float to int" { const float: f64 = 5.99999999999994648725e-01; const float_ptr = &float; - const int_ptr = @ptrCast(&i32, float_ptr); + const int_ptr = @ptrCast(&const i32, float_ptr); const int_val = *int_ptr; assert(int_val == 858993411); } diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 5e453fcbc1..976dc5965c 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -261,7 +261,7 @@ test "generic malloc free" { const a = memAlloc(u8, 10) catch unreachable; memFree(u8, a); } -const some_mem : [100]u8 = undefined; +var some_mem : [100]u8 = undefined; fn memAlloc(comptime T: type, n: usize) error![]T { return @ptrCast(&T, &some_mem[0])[0..n]; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a3ac4e2344..be2750253c 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,14 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) void { + cases.add("@ptrCast discards const qualifier", + \\export fn entry() void { + \\ const x: i32 = 1234; + \\ const y = @ptrCast(&i32, &x); + \\} + , + ".tmp_source.zig:3:15: error: cast discards const qualifier"); + cases.add("comptime slice of undefined pointer non-zero len", \\export fn entry() void { \\ const slice = (&i32)(undefined)[0..1];