diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 98e11e24c9..e54bd58676 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -319,6 +319,9 @@ static bool is_digit(uint8_t c) { } static bool is_printable(uint8_t c) { + if (c == 0) { + return false; + } static const uint8_t printables[] = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:"; for (size_t i = 0; i < array_length(printables); i += 1) { @@ -337,20 +340,12 @@ static void string_literal_escape(Buf *source, Buf *dest) { buf_append_str(dest, "\\\""); } else if (c == '\\') { buf_append_str(dest, "\\\\"); - } else if (c == '\a') { - buf_append_str(dest, "\\a"); - } else if (c == '\b') { - buf_append_str(dest, "\\b"); - } else if (c == '\f') { - buf_append_str(dest, "\\f"); } else if (c == '\n') { buf_append_str(dest, "\\n"); } else if (c == '\r') { buf_append_str(dest, "\\r"); } else if (c == '\t') { buf_append_str(dest, "\\t"); - } else if (c == '\v') { - buf_append_str(dest, "\\v"); } else if (is_printable(c)) { buf_append_char(dest, c); } else { @@ -630,7 +625,19 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { case NodeTypeCharLiteral: { uint8_t c = node->data.char_literal.value; - if (is_printable(c)) { + if (c == '\'') { + fprintf(ar->f, "'\\''"); + } else if (c == '\"') { + fprintf(ar->f, "'\\\"'"); + } else if (c == '\\') { + fprintf(ar->f, "'\\\\'"); + } else if (c == '\n') { + fprintf(ar->f, "'\\n'"); + } else if (c == '\r') { + fprintf(ar->f, "'\\r'"); + } else if (c == '\t') { + fprintf(ar->f, "'\\t'"); + } else if (is_printable(c)) { fprintf(ar->f, "'%c'", c); } else { fprintf(ar->f, "'\\x%02x'", (int)c); diff --git a/src/codegen.cpp b/src/codegen.cpp index 6fe46acbbf..00629bc568 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4988,7 +4988,8 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab LLVMValueRef vector = ir_llvm_value(g, instruction->vector); LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), ""); - gen_store_untyped(g, vector, casted_ptr, get_ptr_align(g, instruction->result_loc->value.type), false); + uint32_t alignment = get_ptr_align(g, instruction->result_loc->value.type); + gen_store_untyped(g, vector, casted_ptr, alignment, false); return result_loc; } @@ -5001,7 +5002,10 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, LLVMPointerType(get_llvm_type(g, vector_type), 0), ""); - return gen_load_untyped(g, casted_ptr, 0, false, ""); + ZigType *array_type = instruction->array->value.type; + assert(array_type->id == ZigTypeIdArray); + uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type); + return gen_load_untyped(g, casted_ptr, alignment, false, ""); } static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable, diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig index 28cde6de01..7407528bf5 100644 --- a/std/zig/parser_test.zig +++ b/std/zig/parser_test.zig @@ -2267,6 +2267,32 @@ test "zig fmt: file ends with struct field" { ); } +test "zig fmt: comments at several places in struct init" { + try testTransform( + \\var bar = Bar{ + \\ .x = 10, // test + \\ .y = "test" + \\ // test + \\}; + \\ + , + \\var bar = Bar{ + \\ .x = 10, // test + \\ .y = "test", // test + \\}; + \\ + ); + + try testCanonical( + \\var bar = Bar{ // test + \\ .x = 10, // test + \\ .y = "test", + \\ // test + \\}; + \\ + ); +} + const std = @import("std"); const mem = std.mem; const warn = std.debug.warn; diff --git a/std/zig/render.zig b/std/zig/render.zig index c6bb51267d..2e034142c2 100644 --- a/std/zig/render.zig +++ b/std/zig/render.zig @@ -2020,7 +2020,13 @@ fn renderTokenOffset( const after_comment_token = tree.tokens.at(token_index + offset); const next_line_indent = switch (after_comment_token.id) { - Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent - indent_delta, + Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => blk: { + if (indent > indent_delta) { + break :blk indent - indent_delta; + } else { + break :blk 0; + } + }, else => indent, }; try stream.writeByteNTimes(' ', next_line_indent); diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig index 70b47c4590..431e3fe272 100644 --- a/test/stage1/behavior/vector.zig +++ b/test/stage1/behavior/vector.zig @@ -74,3 +74,9 @@ test "implicit cast vector to array" { S.doTheTest(); comptime S.doTheTest(); } + +test "array to vector" { + var foo: f32 = 3.14; + var arr = [4]f32{ foo, 1.5, 0.0, 0.0 }; + var vec: @Vector(4, f32) = arr; +} diff --git a/test/translate_c.zig b/test/translate_c.zig index d2a5b72b2b..672075e3b6 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1780,6 +1780,40 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} ); + cases.addC("escape sequences", + \\const char *escapes() { + \\char a = '\'', + \\ b = '\\', + \\ c = '\a', + \\ d = '\b', + \\ e = '\f', + \\ f = '\n', + \\ g = '\r', + \\ h = '\t', + \\ i = '\v', + \\ j = '\0', + \\ k = '\"'; + \\ return "\'\\\a\b\f\n\r\t\v\0\""; + \\} + \\ + , + \\pub export fn escapes() [*c]const u8 { + \\ var a: u8 = u8('\''); + \\ var b: u8 = u8('\\'); + \\ var c: u8 = u8('\x07'); + \\ var d: u8 = u8('\x08'); + \\ var e: u8 = u8('\x0c'); + \\ var f: u8 = u8('\n'); + \\ var g: u8 = u8('\r'); + \\ var h: u8 = u8('\t'); + \\ var i: u8 = u8('\x0b'); + \\ var j: u8 = u8('\x00'); + \\ var k: u8 = u8('\"'); + \\ return c"\'\\\x07\x08\x0c\n\r\t\x0b\x00\""; + \\} + \\ + ); + /////////////// Cases for only stage1 because stage2 behavior is better //////////////// cases.addC("Parameterless function prototypes", \\void foo() {}