diff --git a/src/translate_c.zig b/src/translate_c.zig index ff9e1e5d0d2781b13101385d470ff46b8b154799..388fa8841ea5c2519b7b63a5b7a070d907b4bc98 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -2942,9 +2942,9 @@ fn transCharLiteral( suppress_as: SuppressCast, ) TransError!*ast.Node { const kind = stmt.getKind(); + const val = stmt.getValue(); const int_lit_node = switch (kind) { .Ascii, .UTF8 => blk: { - const val = stmt.getValue(); if (kind == .Ascii) { // C has a somewhat obscure feature called multi-character character // constant @@ -2960,13 +2960,15 @@ fn transCharLiteral( }; break :blk &node.base; }, - .UTF16, .UTF32, .Wide => return revertAndWarn( - rp, - error.UnsupportedTranslation, - @ptrCast(*const clang.Stmt, stmt).getBeginLoc(), - "TODO: support character literal kind {}", - .{kind}, - ), + .Wide, .UTF16, .UTF32 => blk: { + const token = try appendTokenFmt(rp.c, .CharLiteral, "'\\u{{{x}}}'", .{val}); + const node = try rp.c.arena.create(ast.Node.OneToken); + node.* = .{ + .base = .{ .tag = .CharLiteral }, + .token = token, + }; + break :blk &node.base; + }, }; if (suppress_as == .no_as) { return maybeSuppressResult(rp, scope, result_used, int_lit_node); diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index f719d0fe4094a4f40d0795a29b71bc2a2e36f4e6..13952742517de1ca95719d0c193caa4cc04a4273 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -719,4 +719,22 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); + + cases.add("Wide, UTF-16, and UTF-32 character literals", + \\#include + \\#include + \\int main() { + \\ wchar_t wc = L'™'; + \\ int utf16_char = u'™'; + \\ int utf32_char = U'💯'; + \\ if (wc != 8482) abort(); + \\ if (utf16_char != 8482) abort(); + \\ if (utf32_char != 128175) abort(); + \\ unsigned char c = wc; + \\ if (c != 0x22) abort(); + \\ c = utf32_char; + \\ if (c != 0xaf) abort(); + \\ return 0; + \\} + , ""); }