From f55fdc00fcde3cd17ed0ddb94c0997c882dbe6b9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Dec 2017 21:53:52 -0500 Subject: [PATCH] fix const and volatile qualifiers being dropped sometimes in the expression `&const a.b`, the const (and/or volatile) qualifiers would be incorrectly dropped. closes #655 --- doc/docgen.zig | 2 +- src/ir.cpp | 23 ++++++++++++++++------- src/ir_print.cpp | 8 ++++++-- std/base64.zig | 2 +- test/behavior.zig | 1 + test/cases/bugs/655.zig | 12 ++++++++++++ test/cases/bugs/655_other_file.zig | 1 + test/cases/misc.zig | 2 +- 8 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 test/cases/bugs/655.zig create mode 100644 test/cases/bugs/655_other_file.zig diff --git a/doc/docgen.zig b/doc/docgen.zig index 81febb074e..bec12d98b7 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -42,7 +42,7 @@ const State = enum { // TODO look for code segments -fn gen(in: &io.InStream, out: &const io.OutStream) { +fn gen(in: &io.InStream, out: &io.OutStream) { var state = State.Start; while (true) { const byte = in.readByte() %% |err| { diff --git a/src/ir.cpp b/src/ir.cpp index 40f853531f..62b9545348 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1025,7 +1025,7 @@ static IrInstruction *ir_build_ptr_type_of(IrBuilder *irb, Scope *scope, AstNode ptr_type_of_instruction->bit_offset_start = bit_offset_start; ptr_type_of_instruction->bit_offset_end = bit_offset_end; - ir_ref_instruction(align_value, irb->current_basic_block); + if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); ir_ref_instruction(child_type, irb->current_basic_block); return &ptr_type_of_instruction->base; @@ -4897,13 +4897,18 @@ static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *n AstNode *expr_node = node->data.addr_of_expr.op_expr; AstNode *align_expr = node->data.addr_of_expr.align_expr; - if (align_expr == nullptr) { + if (align_expr == nullptr && !is_const && !is_volatile) { return ir_gen_node_extra(irb, expr_node, scope, make_lval_addr(is_const, is_volatile)); } - IrInstruction *align_value = ir_gen_node(irb, align_expr, scope); - if (align_value == irb->codegen->invalid_instruction) - return align_value; + IrInstruction *align_value; + if (align_expr != nullptr) { + align_value = ir_gen_node(irb, align_expr, scope); + if (align_value == irb->codegen->invalid_instruction) + return align_value; + } else { + align_value = nullptr; + } IrInstruction *child_type = ir_gen_node(irb, expr_node, scope); if (child_type == irb->codegen->invalid_instruction) @@ -15959,8 +15964,12 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_of(IrAnalyze *ira, IrInst return ira->codegen->builtin_types.entry_invalid; uint32_t align_bytes; - if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes)) - return ira->codegen->builtin_types.entry_invalid; + if (instruction->align_value != nullptr) { + if (!ir_resolve_align(ira, instruction->align_value->other, &align_bytes)) + return ira->codegen->builtin_types.entry_invalid; + } else { + align_bytes = get_abi_alignment(ira->codegen, child_type); + } ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); out_val->data.x_type = get_pointer_to_type_extra(ira->codegen, child_type, diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 223a012456..b6a7c32dfc 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -886,8 +886,12 @@ static void ir_print_can_implicit_cast(IrPrint *irp, IrInstructionCanImplicitCas } static void ir_print_ptr_type_of(IrPrint *irp, IrInstructionPtrTypeOf *instruction) { - fprintf(irp->f, "&align "); - ir_print_other_instruction(irp, instruction->align_value); + fprintf(irp->f, "&"); + if (instruction->align_value != nullptr) { + fprintf(irp->f, "align("); + ir_print_other_instruction(irp, instruction->align_value); + fprintf(irp->f, ")"); + } const char *const_str = instruction->is_const ? "const " : ""; const char *volatile_str = instruction->is_volatile ? "volatile " : ""; fprintf(irp->f, ":%" PRIu32 ":%" PRIu32 " %s%s", instruction->bit_offset_start, instruction->bit_offset_end, diff --git a/std/base64.zig b/std/base64.zig index 25e438c4fb..840643b565 100644 --- a/std/base64.zig +++ b/std/base64.zig @@ -193,7 +193,7 @@ pub const Base64DecoderWithIgnore = struct { /// Decoding more data than can fit in dest results in error.OutputTooSmall. See also ::calcSizeUpperBound. /// Returns the number of bytes writen to dest. pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) -> %usize { - const decoder = &const decoder_with_ignore.decoder; + const decoder = &decoder_with_ignore.decoder; var src_cursor: usize = 0; var dest_cursor: usize = 0; diff --git a/test/behavior.zig b/test/behavior.zig index bdd428074b..da5b173e17 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -7,6 +7,7 @@ comptime { _ = @import("cases/bitcast.zig"); _ = @import("cases/bool.zig"); _ = @import("cases/bugs/394.zig"); + _ = @import("cases/bugs/655.zig"); _ = @import("cases/cast.zig"); _ = @import("cases/const_slice_child.zig"); _ = @import("cases/defer.zig"); diff --git a/test/cases/bugs/655.zig b/test/cases/bugs/655.zig new file mode 100644 index 0000000000..a0da9d53a2 --- /dev/null +++ b/test/cases/bugs/655.zig @@ -0,0 +1,12 @@ +const std = @import("std"); +const other_file = @import("655_other_file.zig"); + +test "function with &const parameter with type dereferenced by namespace" { + const x: other_file.Integer = 1234; + comptime std.debug.assert(@typeOf(&x) == &const other_file.Integer); + foo(x); +} + +fn foo(x: &const other_file.Integer) { + std.debug.assert(*x == 1234); +} diff --git a/test/cases/bugs/655_other_file.zig b/test/cases/bugs/655_other_file.zig new file mode 100644 index 0000000000..df1df44955 --- /dev/null +++ b/test/cases/bugs/655_other_file.zig @@ -0,0 +1 @@ +pub const Integer = u32; diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 9f4f064f6b..e5e6575fab 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -504,7 +504,7 @@ test "@typeName" { test "volatile load and store" { var number: i32 = 1234; - const ptr = &volatile number; + const ptr = (&volatile i32)(&number); *ptr += 1; assert(*ptr == 1235); }