Commit fd6020c4e2

Andrew Kelley <andrew@ziglang.org>
2019-11-20 22:08:01
update tests, better error messages, update self-hosted tokenizer
1 parent cf2fe25
Changed files (6)
lib
src
src-self-hosted
test
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;
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,
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<ConstCastBadCV>(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)
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);
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);
 }
 
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(