| ... | ... | @@ -780,7 +780,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 780 | 780 | eq_tok = try appendToken(c, .Equal, "="); |
| 781 | 781 | if (decl_init) |expr| { |
| 782 | 782 | const node_or_error = if (expr.getStmtClass() == .StringLiteralClass) |
| 783 | | transStringLiteralAsArray(rp, &c.global_scope.base, @ptrCast(*const clang.StringLiteral, expr), type_node) |
| 783 | transStringLiteralAsArray(rp, &c.global_scope.base, @ptrCast(*const clang.StringLiteral, expr), zigArraySize(rp.c, type_node) catch 0) |
| 784 | 784 | else |
| 785 | 785 | transExprCoercing(rp, scope, expr, .used, .r_value); |
| 786 | 786 | init_node = node_or_error catch |err| switch (err) { |
| ... | ... | @@ -1662,7 +1662,7 @@ fn transDeclStmtOne( |
| 1662 | 1662 | const eq_token = try appendToken(c, .Equal, "="); |
| 1663 | 1663 | var init_node = if (decl_init) |expr| |
| 1664 | 1664 | if (expr.getStmtClass() == .StringLiteralClass) |
| 1665 | | try transStringLiteralAsArray(rp, scope, @ptrCast(*const clang.StringLiteral, expr), type_node) |
| 1665 | try transStringLiteralAsArray(rp, scope, @ptrCast(*const clang.StringLiteral, expr), try zigArraySize(rp.c, type_node)) |
| 1666 | 1666 | else |
| 1667 | 1667 | try transExprCoercing(rp, scope, expr, .used, .r_value) |
| 1668 | 1668 | else |
| ... | ... | @@ -2059,16 +2059,41 @@ fn transStringLiteral( |
| 2059 | 2059 | }; |
| 2060 | 2060 | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 2061 | 2061 | }, |
| 2062 | | .UTF16, .UTF32, .Wide => return revertAndWarn( |
| 2063 | | rp, |
| 2064 | | error.UnsupportedTranslation, |
| 2065 | | @ptrCast(*const clang.Stmt, stmt).getBeginLoc(), |
| 2066 | | "TODO: support string literal kind {s}", |
| 2067 | | .{kind}, |
| 2068 | | ), |
| 2062 | .UTF16, .UTF32, .Wide => { |
| 2063 | const node = try transWideStringLiteral(rp, scope, stmt); |
| 2064 | return maybeSuppressResult(rp, scope, result_used, node); |
| 2065 | }, |
| 2069 | 2066 | } |
| 2070 | 2067 | } |
| 2071 | 2068 | |
| 2069 | /// Translates a wide string literal as a global "anonymous" array of the relevant-sized |
| 2070 | /// integer type + null terminator, and returns an identifier node for it |
| 2071 | fn transWideStringLiteral(rp: RestorePoint, scope: *Scope, stmt: *const clang.StringLiteral) TransError!*ast.Node { |
| 2072 | const str_type = @tagName(stmt.getKind()); |
| 2073 | const mangle = rp.c.getMangle(); |
| 2074 | const name = try std.fmt.allocPrint(rp.c.arena, "zig.{s}_string_{d}", .{ str_type, mangle }); |
| 2075 | |
| 2076 | const const_tok = try appendToken(rp.c, .Keyword_const, "const"); |
| 2077 | const name_tok = try appendIdentifier(rp.c, name); |
| 2078 | const eq_tok = try appendToken(rp.c, .Equal, "="); |
| 2079 | var semi_tok: ast.TokenIndex = undefined; |
| 2080 | |
| 2081 | const lit_array = try transStringLiteralAsArray(rp, scope, stmt, stmt.getLength() + 1); |
| 2082 | |
| 2083 | semi_tok = try appendToken(rp.c, .Semicolon, ";"); |
| 2084 | const var_decl_node = try ast.Node.VarDecl.create(rp.c.arena, .{ |
| 2085 | .name_token = name_tok, |
| 2086 | .mut_token = const_tok, |
| 2087 | .semicolon_token = semi_tok, |
| 2088 | }, .{ |
| 2089 | .visib_token = null, |
| 2090 | .eq_token = eq_tok, |
| 2091 | .init_node = lit_array, |
| 2092 | }); |
| 2093 | try addTopLevelDecl(rp.c, name, &var_decl_node.base); |
| 2094 | return transCreateNodeIdentifier(rp.c, name); |
| 2095 | } |
| 2096 | |
| 2072 | 2097 | /// Parse the size of an array back out from an ast Node. |
| 2073 | 2098 | fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 2074 | 2099 | if (node.castTag(.ArrayType)) |array| { |
| ... | ... | @@ -2081,17 +2106,18 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 2081 | 2106 | } |
| 2082 | 2107 | |
| 2083 | 2108 | /// Translate a string literal to an array of integers. Used when an |
| 2084 | | /// array is initialized from a string literal. `target_node` is the |
| 2085 | | /// array being initialized. If the string literal is larger than the |
| 2086 | | /// array, truncate the string. If the array is larger than the string |
| 2087 | | /// literal, pad the array with 0's |
| 2109 | /// array is initialized from a string literal. `array_size` is the |
| 2110 | /// size of the array being initialized. If the string literal is larger |
| 2111 | /// than the array, truncate the string. If the array is larger than the |
| 2112 | /// string literal, pad the array with 0's |
| 2088 | 2113 | fn transStringLiteralAsArray( |
| 2089 | 2114 | rp: RestorePoint, |
| 2090 | 2115 | scope: *Scope, |
| 2091 | 2116 | stmt: *const clang.StringLiteral, |
| 2092 | | target_node: *ast.Node, |
| 2117 | array_size: usize, |
| 2093 | 2118 | ) TransError!*ast.Node { |
| 2094 | | const array_size = try zigArraySize(rp.c, target_node); |
| 2119 | if (array_size == 0) return error.UnsupportedType; |
| 2120 | |
| 2095 | 2121 | const str_length = stmt.getLength(); |
| 2096 | 2122 | |
| 2097 | 2123 | const expr_base = @ptrCast(*const clang.Expr, stmt); |