| ... | @@ -780,7 +780,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co | ... | @@ -780,7 +780,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 780 | eq_tok = try appendToken(c, .Equal, "="); | 780 | eq_tok = try appendToken(c, .Equal, "="); |
| 781 | if (decl_init) |expr| { | 781 | if (decl_init) |expr| { |
| 782 | const node_or_error = if (expr.getStmtClass() == .StringLiteralClass) | 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 | else | 784 | else |
| 785 | transExprCoercing(rp, scope, expr, .used, .r_value); | 785 | transExprCoercing(rp, scope, expr, .used, .r_value); |
| 786 | init_node = node_or_error catch |err| switch (err) { | 786 | init_node = node_or_error catch |err| switch (err) { |
| ... | @@ -1662,7 +1662,7 @@ fn transDeclStmtOne( | ... | @@ -1662,7 +1662,7 @@ fn transDeclStmtOne( |
| 1662 | const eq_token = try appendToken(c, .Equal, "="); | 1662 | const eq_token = try appendToken(c, .Equal, "="); |
| 1663 | var init_node = if (decl_init) |expr| | 1663 | var init_node = if (decl_init) |expr| |
| 1664 | if (expr.getStmtClass() == .StringLiteralClass) | 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 | else | 1666 | else |
| 1667 | try transExprCoercing(rp, scope, expr, .used, .r_value) | 1667 | try transExprCoercing(rp, scope, expr, .used, .r_value) |
| 1668 | else | 1668 | else |
| ... | @@ -2059,16 +2059,41 @@ fn transStringLiteral( | ... | @@ -2059,16 +2059,41 @@ fn transStringLiteral( |
| 2059 | }; | 2059 | }; |
| 2060 | return maybeSuppressResult(rp, scope, result_used, &node.base); | 2060 | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| 2061 | }, | 2061 | }, |
| 2062 | .UTF16, .UTF32, .Wide => return revertAndWarn( | 2062 | .UTF16, .UTF32, .Wide => { |
| 2063 | rp, | 2063 | const node = try transWideStringLiteral(rp, scope, stmt); |
| 2064 | error.UnsupportedTranslation, | 2064 | return maybeSuppressResult(rp, scope, result_used, node); |
| 2065 | @ptrCast(*const clang.Stmt, stmt).getBeginLoc(), | 2065 | }, |
| 2066 | "TODO: support string literal kind {s}", | | |
| 2067 | .{kind}, | | |
| 2068 | ), | | |
| 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 | /// Parse the size of an array back out from an ast Node. | 2097 | /// Parse the size of an array back out from an ast Node. |
| 2073 | fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { | 2098 | fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 2074 | if (node.castTag(.ArrayType)) |array| { | 2099 | if (node.castTag(.ArrayType)) |array| { |
| ... | @@ -2081,17 +2106,18 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { | ... | @@ -2081,17 +2106,18 @@ fn zigArraySize(c: *Context, node: *ast.Node) TransError!usize { |
| 2081 | } | 2106 | } |
| 2082 | | 2107 | |
| 2083 | /// Translate a string literal to an array of integers. Used when an | 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 | 2109 | /// array is initialized from a string literal. `array_size` is the |
| 2085 | /// array being initialized. If the string literal is larger than the | 2110 | /// size of the array being initialized. If the string literal is larger |
| 2086 | /// array, truncate the string. If the array is larger than the string | 2111 | /// than the array, truncate the string. If the array is larger than the |
| 2087 | /// literal, pad the array with 0's | 2112 | /// string literal, pad the array with 0's |
| 2088 | fn transStringLiteralAsArray( | 2113 | fn transStringLiteralAsArray( |
| 2089 | rp: RestorePoint, | 2114 | rp: RestorePoint, |
| 2090 | scope: *Scope, | 2115 | scope: *Scope, |
| 2091 | stmt: *const clang.StringLiteral, | 2116 | stmt: *const clang.StringLiteral, |
| 2092 | target_node: *ast.Node, | 2117 | array_size: usize, |
| 2093 | ) TransError!*ast.Node { | 2118 | ) TransError!*ast.Node { |
| 2094 | const array_size = try zigArraySize(rp.c, target_node); | 2119 | if (array_size == 0) return error.UnsupportedType; |
| | 2120 | |
| 2095 | const str_length = stmt.getLength(); | 2121 | const str_length = stmt.getLength(); |
| 2096 | | 2122 | |
| 2097 | const expr_base = @ptrCast(*const clang.Expr, stmt); | 2123 | const expr_base = @ptrCast(*const clang.Expr, stmt); |