Commit 73e8e46257

Andrew Kelley <andrew@ziglang.org>
2019-02-10 07:11:30
casting between C pointers and normal pointers
See #1059
1 parent b8cbe38
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -2462,7 +2462,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
 
     ir_ref_instruction(type_value, irb->current_basic_block);
 
-    return &instruction->base;    
+    return &instruction->base;
 }
 
 static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
@@ -6739,7 +6739,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
             atomic_state_field_name);
 
     // set the is_canceled bit
-    IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 
+    IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
             usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
             AtomicRmwOp_or, AtomicOrderSeqCst);
 
@@ -6817,7 +6817,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
             atomic_state_field_name);
 
     // clear the is_suspended bit
-    IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 
+    IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
             usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
             AtomicRmwOp_and, AtomicOrderSeqCst);
 
@@ -6933,7 +6933,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
 
     IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
     IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);
-    IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 
+    IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
             usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
             AtomicRmwOp_or, AtomicOrderSeqCst);
 
@@ -6976,7 +6976,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
 
 
     ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
-    IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 
+    IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
             usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
             AtomicRmwOp_or, AtomicOrderSeqCst);
     IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);
@@ -7008,7 +7008,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
 
     ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
     IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
-    IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 
+    IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
             usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
             AtomicRmwOp_or, AtomicOrderSeqCst);
     IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);
@@ -11279,12 +11279,21 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
     }
 
-    // casting to C pointers
-    if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC) {
-        // cast from integer to C pointer
-        if (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt) {
-            return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
-        }
+    // casting between C pointers and normal pointers
+    if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
+        (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) &&
+        types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
+            actual_type->data.pointer.child_type, source_node,
+            !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
+    {
+        return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);
+    }
+
+    // cast from integer to C pointer
+    if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
+        (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt))
+    {
+        return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
     }
 
     // cast from undefined to anything
@@ -16436,7 +16445,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
         pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
         if (pointee_val == nullptr)
             return ira->codegen->invalid_instruction;
-            
+
         if (pointee_val->special == ConstValSpecialRuntime)
             pointee_val = nullptr;
     }
@@ -17186,7 +17195,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
 static TypeStructField *validate_byte_offset(IrAnalyze *ira,
         IrInstruction *type_value,
         IrInstruction *field_name_value,
-        size_t *byte_offset) 
+        size_t *byte_offset)
 {
     ZigType *container_type = ir_resolve_type(ira, type_value);
     if (type_is_invalid(container_type))
@@ -17360,7 +17369,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
 
     // Loop through the definitions and generate info.
     decl_it = decls_scope->decl_table.entry_iterator();
-    curr_entry = nullptr;    
+    curr_entry = nullptr;
     int definition_index = 0;
     while ((curr_entry = decl_it.next()) != nullptr) {
         // Skip comptime blocks and test functions.
@@ -20312,7 +20321,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
             } else {
                 seenFalse += 1;
             }
-            
+
             if ((seenTrue > 1) || (seenFalse > 1)) {
                 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
                 return ira->codegen->invalid_instruction;
test/stage1/behavior/pointers.zig
@@ -48,3 +48,11 @@ test "assigning integer to C pointer" {
     var ptr: [*c]u8 = 0;
     var ptr2: [*c]u8 = x;
 }
+
+test "implicit cast single item pointer to C pointer and back" {
+    var y: u8 = 11;
+    var x: [*c]u8 = &y;
+    var z: *u8 = x;
+    z.* += 1;
+    expect(y == 12);
+}