diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-01-05 18:50:36 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-01-05 18:50:36 -0500 |
| commit | e621ad014e919521268d3e2c94afadbdadadb59f (patch) | |
| tree | a038e0051b6d8c9b220cb2faa2918eb3f42fa909 | |
| parent | 97e105489085fcf4530b3944499531d76848bbd1 (diff) | |
| download | zig-e621ad014e919521268d3e2c94afadbdadadb59f.tar.gz zig-e621ad014e919521268d3e2c94afadbdadadb59f.zip | |
pass cannot assign to constant test
| -rw-r--r-- | example/cat/main.zig | 8 | ||||
| -rw-r--r-- | src/ir.cpp | 69 | ||||
| -rw-r--r-- | std/cstr.zig | 4 | ||||
| -rw-r--r-- | std/list.zig | 2 | ||||
| -rw-r--r-- | test/cases/enum_with_members.zig | 2 | ||||
| -rw-r--r-- | test/cases/misc.zig | 7 | ||||
| -rw-r--r-- | test/cases/struct.zig | 4 | ||||
| -rw-r--r-- | test/run_tests.cpp | 10 |
8 files changed, 70 insertions, 36 deletions
diff --git a/example/cat/main.zig b/example/cat/main.zig index 1f600843ba..a24b268228 100644 --- a/example/cat/main.zig +++ b/example/cat/main.zig @@ -10,7 +10,7 @@ pub fn main(args: [][]u8) -> %void { for (args[1...]) |arg| { if (str.eql(arg, "-")) { catted_anything = true; - cat_stream(io.stdin) %% |err| return err; + cat_stream(&io.stdin) %% |err| return err; } else if (arg[0] == '-') { return usage(exe); } else { @@ -24,11 +24,11 @@ pub fn main(args: [][]u8) -> %void { defer %%is.close(); catted_anything = true; - cat_stream(is) %% |err| return err; + cat_stream(&is) %% |err| return err; } } if (!catted_anything) { - cat_stream(io.stdin) %% |err| return err; + cat_stream(&io.stdin) %% |err| return err; } io.stdout.flush() %% |err| return err; } @@ -40,7 +40,7 @@ fn usage(exe: []u8) -> %void { return error.Invalid; } -fn cat_stream(is: io.InStream) -> %void { +fn cat_stream(is: &io.InStream) -> %void { var buf: [1024 * 4]u8 = undefined; while (true) { diff --git a/src/ir.cpp b/src/ir.cpp index 6958cfc2e1..0e918e9a88 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -721,17 +721,23 @@ static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_in return new_instruction; } -static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, VariableTableEntry *var) { +static IrInstruction *ir_build_var_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, + VariableTableEntry *var, bool is_const) +{ IrInstructionVarPtr *instruction = ir_build_instruction<IrInstructionVarPtr>(irb, scope, source_node); instruction->var = var; + instruction->is_const = is_const; ir_ref_var(var); return &instruction->base; } -static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, VariableTableEntry *var) { - IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->scope, old_instruction->source_node, var); +static IrInstruction *ir_build_var_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, + VariableTableEntry *var, bool is_const) +{ + IrInstruction *new_instruction = ir_build_var_ptr(irb, old_instruction->scope, + old_instruction->source_node, var, is_const); ir_link_new_instruction(new_instruction, old_instruction); return new_instruction; @@ -3401,7 +3407,7 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld { TldVar *tld_var = (TldVar *)tld; VariableTableEntry *var = tld_var->var; - IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var); + IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var, false); if (lval != LValPurposeNone) return var_ptr; else @@ -3449,7 +3455,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, VariableTableEntry *var = find_variable(irb->codegen, scope, variable_name); if (var) { - IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var); + IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, node, var, lval == LValPurposeAddressOfConst); if (lval != LValPurposeNone) return var_ptr; else @@ -4309,7 +4315,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value); - IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); + IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var, false); AstNode *index_var_source_node; VariableTableEntry *index_var; @@ -4327,7 +4333,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, zero); - IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); + IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var, false); IrBasicBlock *cond_block = ir_build_basic_block(irb, child_scope, "ForCond"); @@ -4351,7 +4357,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo } else { elem_val = ir_build_load_ptr(irb, child_scope, node, elem_ptr); } - ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val); + ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, elem_var_ptr, elem_val)); LoopStackItem *loop_stack_item = irb->loop_stack.add_one(); loop_stack_item->break_block = end_block; @@ -4365,7 +4371,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo ir_set_cursor_at_end(irb, continue_block); IrInstruction *new_index_val = ir_build_bin_op(irb, child_scope, node, IrBinOpAdd, index_val, one, false); - ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val); + ir_mark_gen(ir_build_store_ptr(irb, child_scope, node, index_ptr, new_index_val)); ir_build_br(irb, child_scope, node, cond_block, is_comptime); ir_set_cursor_at_end(irb, end_block); @@ -7545,9 +7551,15 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal size_t next_proto_i = 0; if (first_arg_ptr) { - IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); - if (first_arg->value.type->id == TypeTableEntryIdInvalid) - return ira->codegen->builtin_types.entry_invalid; + IrInstruction *first_arg; + assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer); + if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) { + first_arg = first_arg_ptr; + } else { + first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); + if (first_arg->value.type->id == TypeTableEntryIdInvalid) + return ira->codegen->builtin_types.entry_invalid; + } if (!ir_analyze_fn_call_generic_arg(ira, fn_proto_node, first_arg, &impl_fn->child_scope, &next_proto_i, generic_id, &fn_type_id, casted_args, impl_fn)) @@ -7612,9 +7624,15 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); size_t next_arg_index = 0; if (first_arg_ptr) { - IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); - if (first_arg->value.type->id == TypeTableEntryIdInvalid) - return ira->codegen->builtin_types.entry_invalid; + IrInstruction *first_arg; + assert(first_arg_ptr->value.type->id == TypeTableEntryIdPointer); + if (handle_is_ptr(first_arg_ptr->value.type->data.pointer.child_type)) { + first_arg = first_arg_ptr; + } else { + first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); + if (first_arg->value.type->id == TypeTableEntryIdInvalid) + return ira->codegen->builtin_types.entry_invalid; + } TypeTableEntry *param_type = fn_type_id->param_info[next_arg_index].type; if (param_type->id == TypeTableEntryIdInvalid) @@ -8090,7 +8108,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP return resolved_type; } -static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, VariableTableEntry *var) { +static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruction, + VariableTableEntry *var, bool is_const_ptr) +{ assert(var->value.type); if (var->value.type->id == TypeTableEntryIdInvalid) return var->value.type; @@ -8110,9 +8130,10 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { ConstPtrSpecial ptr_special = is_comptime ? ConstPtrSpecialInline : ConstPtrSpecialNone; - return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, false, ptr_special, var->src_is_const); + bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; + return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, false, ptr_special, is_const); } else { - ir_build_var_ptr_from(&ira->new_irb, instruction, var); + ir_build_var_ptr_from(&ira->new_irb, instruction, var, false); type_ensure_zero_bits_known(ira->codegen, var->value.type); return get_pointer_to_type(ira->codegen, var->value.type, var->src_is_const); } @@ -8120,7 +8141,7 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { VariableTableEntry *var = var_ptr_instruction->var; - return ir_analyze_var_ptr(ira, &var_ptr_instruction->base, var); + return ir_analyze_var_ptr(ira, &var_ptr_instruction->base, var, var_ptr_instruction->is_const); } static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) { @@ -8313,7 +8334,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source { TldVar *tld_var = (TldVar *)tld; VariableTableEntry *var = tld_var->var; - return ir_analyze_var_ptr(ira, source_instruction, var); + return ir_analyze_var_ptr(ira, source_instruction, var, false); } case TldIdFn: { @@ -8549,6 +8570,12 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru if (value->value.type->id == TypeTableEntryIdInvalid) return value->value.type; + assert(ptr->value.type->id == TypeTableEntryIdPointer); + if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) { + ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); + return ira->codegen->builtin_types.entry_invalid; + } + TypeTableEntry *child_type = ptr->value.type->data.pointer.child_type; IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type); if (casted_value == ira->codegen->invalid_instruction) @@ -8580,7 +8607,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr; VariableTableEntry *var = var_ptr_inst->var; new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.scope, - store_ptr_instruction->base.source_node, var); + store_ptr_instruction->base.source_node, var, false); assert(var->mem_slot_index != SIZE_MAX); ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; mem_slot->special = ConstValSpecialRuntime; diff --git a/std/cstr.zig b/std/cstr.zig index e3755b62df..cf1c020ccd 100644 --- a/std/cstr.zig +++ b/std/cstr.zig @@ -39,7 +39,7 @@ pub const CBuf = struct { /// Must deinitialize with deinit. pub fn initEmpty(allocator: &Allocator) -> %CBuf { - const self = CBuf { + var self = CBuf { .list = List(u8).init(allocator), }; %return self.resize(0); @@ -48,7 +48,7 @@ pub const CBuf = struct { /// Must deinitialize with deinit. pub fn initFromMem(allocator: &Allocator, m: []const u8) -> %CBuf { - const self = CBuf { + var self = CBuf { .list = List(u8).init(allocator), }; %return self.resize(m.len); diff --git a/std/list.zig b/std/list.zig index 52a6eb3095..69f17df7f4 100644 --- a/std/list.zig +++ b/std/list.zig @@ -23,7 +23,7 @@ pub fn List(inline T: type) -> type{ l.allocator.free(T, l.items); } - pub fn toSlice(l: &Self) -> []T { + pub fn toSlice(l: &const Self) -> []const T { return l.items[0...l.len]; } diff --git a/test/cases/enum_with_members.zig b/test/cases/enum_with_members.zig index 9be2d0f749..7bcc2ac01f 100644 --- a/test/cases/enum_with_members.zig +++ b/test/cases/enum_with_members.zig @@ -6,7 +6,7 @@ const ET = enum { SINT: i32, UINT: u32, - pub fn print(a: &ET, buf: []u8) -> %usize { + pub fn print(a: &const ET, buf: []u8) -> %usize { return switch (*a) { ET.SINT => |x| { io.bufPrintInt(i32, buf, x) }, ET.UINT => |x| { io.bufPrintInt(u32, buf, x) }, diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 4f25cb90d5..45966f1d20 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -490,3 +490,10 @@ const test_pointer_to_void_return_type_x = void{}; fn testPointerToVoidReturnType2() -> &const void { return &test_pointer_to_void_return_type_x; } + + +fn nonConstPtrToAliasedType() { + @setFnTest(this); + const int = i32; + assert(?&int == ?&i32); +} diff --git a/test/cases/struct.zig b/test/cases/struct.zig index efe476d808..930aa79db1 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -155,7 +155,7 @@ fn memberFunctions() { } const MemberFnRand = struct { seed: u32, - pub fn getSeed(r: MemberFnRand) -> u32 { + pub fn getSeed(r: &const MemberFnRand) -> u32 { r.seed } }; @@ -184,7 +184,7 @@ fn emptyStructMethodCall() { assert(es.method() == 1234); } const EmptyStruct = struct { - fn method(es: EmptyStruct) -> i32 { + fn method(es: &const EmptyStruct) -> i32 { 1234 } }; diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 5d05245888..4d1f5ed60d 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -548,7 +548,7 @@ const B = struct { const C = struct { x: i32, - fn d(c: C) { + fn d(c: &const C) { %%io.stdout.printf("OK\n"); } }; @@ -577,13 +577,13 @@ const io = @import("std").io; const Foo = struct { field1: Bar, - fn method(a: &Foo) -> bool { true } + fn method(a: &const Foo) -> bool { true } }; const Bar = struct { field2: i32, - fn method(b: &Bar) -> bool { true } + fn method(b: &const Bar) -> bool { true } }; pub fn main(args: [][]u8) -> %void { @@ -787,14 +787,14 @@ fn f(a : unreachable) {} fn f() { 3 = 3; } - )SOURCE", 1, ".tmp_source.zig:3:5: error: invalid assignment target"); + )SOURCE", 1, ".tmp_source.zig:3:7: error: cannot assign to constant"); add_compile_fail_case("assign to constant variable", R"SOURCE( fn f() { const a = 3; a = 4; } - )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant"); + )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); add_compile_fail_case("use of undeclared identifier", R"SOURCE( fn f() { |
