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" {
379379
380380 std.testing.expect(indexOfIgnoreCase("FOO foo", "fOo").? == 0);
381381}
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(
1212 return writer.writeAll(bytes);
1313 }
1414 try writer.writeAll("@\"");
15 try formatEscapes(bytes, fmt, options, writer);
15 try formatEscapes(bytes, "", options, writer);
1616 try writer.writeByte('"');
1717}
1818
......@@ -32,6 +32,9 @@ pub fn isValidId(bytes: []const u8) bool {
3232 return std.zig.Token.getKeyword(bytes) == null;
3333}
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.
3538pub fn formatEscapes(
3639 bytes: []const u8,
3740 comptime fmt: []const u8,
......@@ -43,8 +46,24 @@ pub fn formatEscapes(
4346 '\r' => try writer.writeAll("\\r"),
4447 '\t' => try writer.writeAll("\\t"),
4548 '\\' => try writer.writeAll("\\\\"),
46 '"' => try writer.writeAll("\\\""),
47 '\'' => try writer.writeAll("\\'"),
49 '"' => {
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 },
4867 ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte),
4968 // Use hex escapes for rest any unprintable characters.
5069 else => {
......@@ -54,7 +73,10 @@ pub fn formatEscapes(
5473 };
5574}
5675
57/// Return a Formatter for Zig Escapes
76/// 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.
5880pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {
5981 return .{ .data = bytes };
6082}
......@@ -67,6 +89,9 @@ test "escape invalid identifiers" {
6789 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
6890 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
6991 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 '"
7196 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
7297}
src/clang.zig+10
......@@ -583,6 +583,16 @@ pub const MacroQualifiedType = opaque {
583583 extern fn ZigClangMacroQualifiedType_getModifiedType(*const MacroQualifiedType) QualType;
584584};
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
586596pub const MemberExpr = opaque {
587597 pub const getBase = ZigClangMemberExpr_getBase;
588598 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
24752475
24762476fn transCreateCharLitNode(c: *Context, narrow: bool, val: u32) TransError!Node {
24772477 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)})})
24792479 else
24802480 try std.fmt.allocPrint(c.arena, "'\\u{{{x}}}'", .{val}));
24812481}
......@@ -3827,6 +3827,20 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
38273827 const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty);
38283828 return transQualType(c, scope, macroqualified_ty.getModifiedType(), source_loc);
38293829 },
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 },
38303844 else => {
38313845 const type_name = c.str(ty.getTypeClassName());
38323846 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 {
995995
996996 const compile_error_tok = try c.addToken(.builtin, "@compileError");
997997 _ = 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)});
999999 const err_msg = try c.addNode(.{
10001000 .tag = .string_literal,
10011001 .main_token = err_msg_tok,
......@@ -2265,7 +2265,7 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
22652265 _ = try c.addToken(.l_paren, "(");
22662266 const res = try c.addNode(.{
22672267 .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)}),
22692269 .data = undefined,
22702270 });
22712271 _ = try c.addToken(.r_paren, ")");
......@@ -2347,7 +2347,7 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
23472347 _ = try c.addToken(.l_paren, "(");
23482348 const res = try c.addNode(.{
23492349 .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)}),
23512351 .data = undefined,
23522352 });
23532353 _ = try c.addToken(.r_paren, ")");
src/zig_clang.cpp+10
......@@ -2613,6 +2613,16 @@ struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct
26132613 return bitcast(casted->getModifiedType());
26142614}
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
26162626struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
26172627 auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
26182628 return bitcast(casted->getNamedType());
src/zig_clang.h+4
......@@ -1164,6 +1164,10 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(co
11641164
11651165ZIG_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
11671171ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *);
11681172ZIG_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 {
10541054 \\ return 0;
10551055 \\}
10561056 , "");
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 , "");
10571076}