diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 0f9d0a59cf..ebe396e145 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1725,11 +1725,6 @@ test "zig fmt: multiline string" { \\ \\two) \\ \\three \\ ; - \\ const s2 = - \\ c\\one - \\ c\\two) - \\ c\\three - \\ ; \\ const s3 = // hi \\ \\one \\ \\two) @@ -1746,7 +1741,6 @@ test "zig fmt: values" { \\ 1; \\ 1.0; \\ "string"; - \\ c"cstring"; \\ 'c'; \\ true; \\ false; diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index f17adae648..2e89669e2c 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -351,7 +351,6 @@ pub const Tokenizer = struct { Start, Identifier, Builtin, - C, StringLiteral, StringLiteralBackslash, MultilineStringLiteralLine, @@ -427,10 +426,6 @@ pub const Tokenizer = struct { ' ', '\n', '\t', '\r' => { result.start = self.index + 1; }, - 'c' => { - state = State.C; - result.id = Token.Id.Identifier; - }, '"' => { state = State.StringLiteral; result.id = Token.Id.StringLiteral; @@ -438,7 +433,7 @@ pub const Tokenizer = struct { '\'' => { state = State.CharLiteral; }, - 'a'...'b', 'd'...'z', 'A'...'Z', '_' => { + 'a'...'z', 'A'...'Z', '_' => { state = State.Identifier; result.id = Token.Id.Identifier; }, @@ -730,20 +725,6 @@ pub const Tokenizer = struct { }, else => break, }, - State.C => switch (c) { - '\\' => { - state = State.Backslash; - result.id = Token.Id.MultilineStringLiteralLine; - }, - '"' => { - state = State.StringLiteral; - result.id = Token.Id.StringLiteral; - }, - 'a'...'z', 'A'...'Z', '_', '0'...'9' => { - state = State.Identifier; - }, - else => break, - }, State.StringLiteral => switch (c) { '\\' => { state = State.StringLiteralBackslash; @@ -1204,7 +1185,6 @@ pub const Tokenizer = struct { } else if (self.index == self.buffer.len) { switch (state) { State.Start, - State.C, State.IntegerLiteral, State.IntegerLiteralWithRadix, State.IntegerLiteralWithRadixHex, diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index daa60fcb25..754224d92c 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -698,10 +698,9 @@ fn transStringLiteral( len = 0; for (str) |c| len += escapeChar(c, &char_buf).len; - const buf = try rp.c.a().alloc(u8, len + "c\"\"".len); - buf[0] = 'c'; - buf[1] = '"'; - writeEscapedString(buf[2..], str); + const buf = try rp.c.a().alloc(u8, len + "\"\"".len); + buf[0] = '"'; + writeEscapedString(buf[1..], str); buf[buf.len - 1] = '"'; const token = try appendToken(rp.c, .StringLiteral, buf); diff --git a/src/ir.cpp b/src/ir.cpp index 3ac3ac8ec1..03ec3c0436 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -69,6 +69,7 @@ enum ConstCastResultId { ConstCastResultIdArrayChild, ConstCastResultIdBadNullTermArrays, ConstCastResultIdPtrLens, + ConstCastResultIdCV, }; struct ConstCastOnly; @@ -94,6 +95,7 @@ struct ConstCastArrayMismatch; struct ConstCastBadAllowsZero; struct ConstCastBadNullTermArrays; struct ConstCastBadPtrLens; +struct ConstCastBadCV; struct ConstCastOnly { ConstCastResultId id; @@ -113,6 +115,7 @@ struct ConstCastOnly { ConstCastBadAllowsZero *bad_allows_zero; ConstCastBadNullTermArrays *bad_null_term_arrays; ConstCastBadPtrLens *bad_ptr_lens; + ConstCastBadCV *bad_cv; } data; }; @@ -177,6 +180,10 @@ struct ConstCastBadPtrLens { ZigType *actual_type; }; +struct ConstCastBadCV { + ZigType *wanted_type; + ZigType *actual_type; +}; static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, @@ -9863,6 +9870,17 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return result; } + bool ok_cv_qualifiers = + (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && + (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile); + if (!ok_cv_qualifiers) { + result.id = ConstCastResultIdCV; + result.data.bad_cv = allocate_nonzero(1); + result.data.bad_cv->wanted_type = wanted_ptr_type; + result.data.bad_cv->actual_type = actual_ptr_type; + return result; + } + ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type, actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const); if (child.id == ConstCastResultIdInvalid) @@ -9902,8 +9920,6 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted return result; } if (type_has_bits(wanted_type) == type_has_bits(actual_type) && - (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) && - (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) && actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host && actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes && get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type)) @@ -12595,6 +12611,20 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa } break; } + case ConstCastResultIdCV: { + ZigType *wanted_type = cast_result->data.bad_cv->wanted_type; + ZigType *actual_type = cast_result->data.bad_cv->actual_type; + bool ok_const = !actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const; + bool ok_volatile = !actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile; + if (!ok_const) { + add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("cast discards const qualifier")); + } else if (!ok_volatile) { + add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("cast discards volatile qualifier")); + } else { + zig_unreachable(); + } + break; + } case ConstCastResultIdFnIsGeneric: add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("only one of the functions is generic")); @@ -12987,7 +13017,9 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst wanted_type->data.pointer.ptr_len == PtrLenNull) && actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && - actual_type->data.pointer.child_type->id == ZigTypeIdArray) + actual_type->data.pointer.child_type->id == ZigTypeIdArray && + (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) && + (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile)) { if (wanted_type->data.pointer.ptr_len != PtrLenNull || actual_type->data.pointer.child_type->data.array.is_null_terminated) diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 3343580991..20122b681a 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -784,7 +784,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ strValue = strValue orelse ""; \\} , - "tmp.zig:3:32: error: cast discards const qualifier", + "tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0]null u8'", + "tmp.zig:3:32: note: cast discards const qualifier", ); cases.add( @@ -1323,7 +1324,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ ptr_opt_many_ptr = c_ptr; \\} \\export fn entry2() void { - \\ var buf: [4]u8 = "aoeu"; + \\ var buf: [4]u8 = "aoeu".*; \\ var slice: []u8 = &buf; \\ var opt_many_ptr: [*]u8 = slice.ptr; \\ var ptr_opt_many_ptr = &opt_many_ptr; @@ -1518,7 +1519,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "reading past end of pointer casted array", \\comptime { - \\ const array = "aoeu"; + \\ const array: [4]u8 = "aoeu".*; \\ const slice = array[1..]; \\ const int_ptr = @ptrCast(*const u24, slice.ptr); \\ const deref = int_ptr.*; @@ -3356,7 +3357,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ return a; \\} , - "tmp.zig:3:12: error: expected type 'i32', found '[*]const u8'", + "tmp.zig:3:12: error: expected type 'i32', found '*const [1]null u8'", ); cases.add( @@ -3827,12 +3828,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "array concatenation with wrong type", \\const src = "aoeu"; - \\const derp = @as(usize, 1234); + \\const derp: usize = 1234; \\const a = derp ++ "foo"; \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } , - "tmp.zig:3:11: error: expected array or C string literal, found 'usize'", + "tmp.zig:3:11: error: expected array, found 'usize'", ); cases.add( @@ -6207,11 +6208,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "calling var args extern function, passing array instead of pointer", \\export fn entry() void { - \\ foo("hello",); + \\ foo("hello".*,); \\} \\pub extern fn foo(format: *const u8, ...) void; , - "tmp.zig:2:9: error: expected type '*const u8', found '[5]u8'", + "tmp.zig:2:16: error: expected type '*const u8', found '[5]null u8'", ); cases.add( @@ -6777,7 +6778,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} , "tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'", - "tmp.zig:4:22: note: pointer type child 'i32' cannot cast into pointer type child '[1]i32'", + "tmp.zig:4:22: note: cast discards const qualifier", ); cases.add( diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig index 70688aa09c..f9de9fecb7 100644 --- a/test/stage1/c_abi/main.zig +++ b/test/stage1/c_abi/main.zig @@ -119,7 +119,7 @@ export fn zig_bool(x: bool) void { extern fn c_array([10]u8) void; test "C ABI array" { - var array: [10]u8 = "1234567890"; + var array: [10]u8 = "1234567890".*; c_array(array); }