authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-27 02:25:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-27 02:25:58-07:00
log9e8943736e34d28d1ea62229d6ca708303cd0eba
tree878057b9513b6801a19e60ab47aa923f575fbb27
parentd91605e27eb25ae9175f6e92d5f9f9db1ce6a714
parent490654c332f2d8eaf7edffa35ea0523800df998d

Merge remote-tracking branch 'origin/master' into llvm12


8 files changed, 111 insertions(+), 9 deletions(-)

lib/std/ascii.zig+20
...@@ -379,3 +379,23 @@ test "indexOfIgnoreCase" {...@@ -379,3 +379,23 @@ test "indexOfIgnoreCase" {
379379
380 std.testing.expect(indexOfIgnoreCase("FOO foo", "fOo").? == 0);380 std.testing.expect(indexOfIgnoreCase("FOO foo", "fOo").? == 0);
381}381}
382
383/// Compares two slices of numbers lexicographically. O(n).
384pub fn orderIgnoreCase(lhs: []const u8, rhs: []const u8) std.math.Order {
385 const n = std.math.min(lhs.len, rhs.len);
386 var i: usize = 0;
387 while (i < n) : (i += 1) {
388 switch (std.math.order(toLower(lhs[i]), toLower(rhs[i]))) {
389 .eq => continue,
390 .lt => return .lt,
391 .gt => return .gt,
392 }
393 }
394 return std.math.order(lhs.len, rhs.len);
395}
396
397/// Returns true if lhs < rhs, false otherwise
398/// TODO rename "IgnoreCase" to "Insensitive" in this entire file.
399pub fn lessThanIgnoreCase(lhs: []const u8, rhs: []const u8) bool {
400 return orderIgnoreCase(lhs, rhs) == .lt;
401}
lib/std/zig/fmt.zig+30-5
...@@ -12,7 +12,7 @@ pub fn formatId(...@@ -12,7 +12,7 @@ pub fn formatId(
12 return writer.writeAll(bytes);12 return writer.writeAll(bytes);
13 }13 }
14 try writer.writeAll("@\"");14 try writer.writeAll("@\"");
15 try formatEscapes(bytes, fmt, options, writer);15 try formatEscapes(bytes, "", options, writer);
16 try writer.writeByte('"');16 try writer.writeByte('"');
17}17}
1818
...@@ -32,6 +32,9 @@ pub fn isValidId(bytes: []const u8) bool {...@@ -32,6 +32,9 @@ pub fn isValidId(bytes: []const u8) bool {
32 return std.zig.Token.getKeyword(bytes) == null;32 return std.zig.Token.getKeyword(bytes) == null;
33}33}
3434
35/// Print the string as escaped contents of a double quoted or single-quoted string.
36/// Format `{}` treats contents as a double-quoted string.
37/// Format `{'}` treats contents as a single-quoted string.
35pub fn formatEscapes(38pub fn formatEscapes(
36 bytes: []const u8,39 bytes: []const u8,
37 comptime fmt: []const u8,40 comptime fmt: []const u8,
...@@ -43,8 +46,24 @@ pub fn formatEscapes(...@@ -43,8 +46,24 @@ pub fn formatEscapes(
43 '\r' => try writer.writeAll("\\r"),46 '\r' => try writer.writeAll("\\r"),
44 '\t' => try writer.writeAll("\\t"),47 '\t' => try writer.writeAll("\\t"),
45 '\\' => try writer.writeAll("\\\\"),48 '\\' => try writer.writeAll("\\\\"),
46 '"' => try writer.writeAll("\\\""),49 '"' => {
47 '\'' => try writer.writeAll("\\'"),50 if (fmt.len == 1 and fmt[0] == '\'') {
51 try writer.writeByte('"');
52 } else if (fmt.len == 0) {
53 try writer.writeAll("\\\"");
54 } else {
55 @compileError("expected {} or {'}, found {" ++ fmt ++ "}");
56 }
57 },
58 '\'' => {
59 if (fmt.len == 1 and fmt[0] == '\'') {
60 try writer.writeAll("\\'");
61 } else if (fmt.len == 0) {
62 try writer.writeByte('\'');
63 } else {
64 @compileError("expected {} or {'}, found {" ++ fmt ++ "}");
65 }
66 },
48 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),67 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),
49 // Use hex escapes for rest any unprintable characters.68 // Use hex escapes for rest any unprintable characters.
50 else => {69 else => {
...@@ -54,7 +73,10 @@ pub fn formatEscapes(...@@ -54,7 +73,10 @@ pub fn formatEscapes(
54 };73 };
55}74}
5675
57/// Return a Formatter for Zig Escapes76/// Return a Formatter for Zig Escapes of a double quoted string.
77/// The format specifier must be one of:
78/// * `{}` treats contents as a double-quoted string.
79/// * `{'}` treats contents as a single-quoted string.
58pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {80pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {
59 return .{ .data = bytes };81 return .{ .data = bytes };
60}82}
...@@ -67,6 +89,9 @@ test "escape invalid identifiers" {...@@ -67,6 +89,9 @@ test "escape invalid identifiers" {
67 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});89 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
68 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});90 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
69 try expectFmt(91 try expectFmt(
70 \\" \\ hi \x07 \x11 \" derp \'"92 \\" \\ hi \x07 \x11 " derp \'"
93 , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
94 try expectFmt(
95 \\" \\ hi \x07 \x11 \" derp '"
71 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});96 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
72}97}
src/clang.zig+10
...@@ -583,6 +583,16 @@ pub const MacroQualifiedType = opaque {...@@ -583,6 +583,16 @@ pub const MacroQualifiedType = opaque {
583 extern fn ZigClangMacroQualifiedType_getModifiedType(*const MacroQualifiedType) QualType;583 extern fn ZigClangMacroQualifiedType_getModifiedType(*const MacroQualifiedType) QualType;
584};584};
585585
586pub const TypeOfType = opaque {
587 pub const getUnderlyingType = ZigClangTypeOfType_getUnderlyingType;
588 extern fn ZigClangTypeOfType_getUnderlyingType(*const TypeOfType) QualType;
589};
590
591pub const TypeOfExprType = opaque {
592 pub const getUnderlyingExpr = ZigClangTypeOfExprType_getUnderlyingExpr;
593 extern fn ZigClangTypeOfExprType_getUnderlyingExpr(*const TypeOfExprType) *const Expr;
594};
595
586pub const MemberExpr = opaque {596pub const MemberExpr = opaque {
587 pub const getBase = ZigClangMemberExpr_getBase;597 pub const getBase = ZigClangMemberExpr_getBase;
588 extern fn ZigClangMemberExpr_getBase(*const MemberExpr) *const Expr;598 extern fn ZigClangMemberExpr_getBase(*const MemberExpr) *const Expr;
src/translate_c.zig+15-1
...@@ -2475,7 +2475,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined...@@ -2475,7 +2475,7 @@ fn transPredefinedExpr(c: *Context, scope: *Scope, expr: *const clang.Predefined
24752475
2476fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {2476fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
2477 return Tag.char_literal.create(c.arena, if (narrow)2477 return Tag.char_literal.create(c.arena, if (narrow)
2478 try std.fmt.allocPrint(c.arena, "'{s}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})2478 try std.fmt.allocPrint(c.arena, "'{'}'", .{std.zig.fmtEscapes(&.{@intCast(u8, val)})})
2479 else2479 else
2480 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));2480 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
2481}2481}
...@@ -3827,6 +3827,20 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan...@@ -3827,6 +3827,20 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
3827 const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty);3827 const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty);
3828 return transQualType(c, scope, macroqualified_ty.getModifiedType(), source_loc);3828 return transQualType(c, scope, macroqualified_ty.getModifiedType(), source_loc);
3829 },3829 },
3830 .TypeOf => {
3831 const typeof_ty = @ptrCast(*const clang.TypeOfType, ty);
3832 return transQualType(c, scope, typeof_ty.getUnderlyingType(), source_loc);
3833 },
3834 .TypeOfExpr => {
3835 const typeofexpr_ty = @ptrCast(*const clang.TypeOfExprType, ty);
3836 const underlying_expr = transExpr(c, scope, typeofexpr_ty.getUnderlyingExpr(), .used) catch |err| switch (err) {
3837 error.UnsupportedTranslation => {
3838 return fail(c, error.UnsupportedType, source_loc, "unsupported underlying expression for TypeOfExpr", .{});
3839 },
3840 else => |e| return e,
3841 };
3842 return Tag.typeof.create(c.arena, underlying_expr);
3843 },
3830 else => {3844 else => {
3831 const type_name = c.str(ty.getTypeClassName());3845 const type_name = c.str(ty.getTypeClassName());
3832 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});3846 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});
src/translate_c/ast.zig+3-3
...@@ -995,7 +995,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -995,7 +995,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
995995
996 const compile_error_tok = try c.addToken(.builtin, "@compileError");996 const compile_error_tok = try c.addToken(.builtin, "@compileError");
997 _ = try c.addToken(.l_paren, "(");997 _ = try c.addToken(.l_paren, "(");
998 const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(payload.mangled)});998 const err_msg_tok = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(payload.mangled)});
999 const err_msg = try c.addNode(.{999 const err_msg = try c.addNode(.{
1000 .tag = .string_literal,1000 .tag = .string_literal,
1001 .main_token = err_msg_tok,1001 .main_token = err_msg_tok,
...@@ -2265,7 +2265,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {...@@ -2265,7 +2265,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
2265 _ = try c.addToken(.l_paren, "(");2265 _ = try c.addToken(.l_paren, "(");
2266 const res = try c.addNode(.{2266 const res = try c.addNode(.{
2267 .tag = .string_literal,2267 .tag = .string_literal,
2268 .main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),2268 .main_token = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(some)}),
2269 .data = undefined,2269 .data = undefined,
2270 });2270 });
2271 _ = try c.addToken(.r_paren, ")");2271 _ = try c.addToken(.r_paren, ")");
...@@ -2347,7 +2347,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {...@@ -2347,7 +2347,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
2347 _ = try c.addToken(.l_paren, "(");2347 _ = try c.addToken(.l_paren, "(");
2348 const res = try c.addNode(.{2348 const res = try c.addNode(.{
2349 .tag = .string_literal,2349 .tag = .string_literal,
2350 .main_token = try c.addTokenFmt(.string_literal, "\"{s}\"", .{std.zig.fmtEscapes(some)}),2350 .main_token = try c.addTokenFmt(.string_literal, "\"{}\"", .{std.zig.fmtEscapes(some)}),
2351 .data = undefined,2351 .data = undefined,
2352 });2352 });
2353 _ = try c.addToken(.r_paren, ")");2353 _ = try c.addToken(.r_paren, ")");
src/zig_clang.cpp+10
...@@ -2613,6 +2613,16 @@ struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct...@@ -2613,6 +2613,16 @@ struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct
2613 return bitcast(casted->getModifiedType());2613 return bitcast(casted->getModifiedType());
2614}2614}
26152615
2616struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const struct ZigClangTypeOfType *self) {
2617 auto casted = reinterpret_cast<const clang::TypeOfType *>(self);
2618 return bitcast(casted->getUnderlyingType());
2619}
2620
2621const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *self) {
2622 auto casted = reinterpret_cast<const clang::TypeOfExprType *>(self);
2623 return reinterpret_cast<const struct ZigClangExpr *>(casted->getUnderlyingExpr());
2624}
2625
2616struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {2626struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
2617 auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);2627 auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
2618 return bitcast(casted->getNamedType());2628 return bitcast(casted->getNamedType());
src/zig_clang.h+4
...@@ -1164,6 +1164,10 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(co...@@ -1164,6 +1164,10 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(co
11641164
1165ZIG_EXTERN_C struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *);1165ZIG_EXTERN_C struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *);
11661166
1167ZIG_EXTERN_C struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const struct ZigClangTypeOfType *);
1168
1169ZIG_EXTERN_C const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *);
1170
1167ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);1171ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);
1168ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *);1172ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *);
11691173
test/run_translated_c.zig+19
...@@ -1054,4 +1054,23 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1054,4 +1054,23 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1054 \\ return 0;1054 \\ return 0;
1055 \\}1055 \\}
1056 , "");1056 , "");
1057
1058 cases.add("typeof operator",
1059 \\#include <stdlib.h>
1060 \\static int FOO = 42;
1061 \\typedef typeof(FOO) foo_type;
1062 \\typeof(foo_type) myfunc(typeof(FOO) x) { return (typeof(FOO)) x; }
1063 \\int main(void) {
1064 \\ int x = FOO;
1065 \\ typeof(x) y = x;
1066 \\ foo_type z = y;
1067 \\ if (x != y) abort();
1068 \\ if (myfunc(z) != x) abort();
1069 \\
1070 \\ const char *my_string = "bar";
1071 \\ typeof (typeof (my_string)[4]) string_arr = {"a","b","c","d"};
1072 \\ if (string_arr[0][0] != 'a' || string_arr[3][0] != 'd') abort();
1073 \\ return 0;
1074 \\}
1075 , "");
1057}1076}