| author | |
| committer | |
| log | 9716a1c3ab3f56dcef7a70aac597f186a69714fc |
| tree | 501f29b5a9adcd0f5e20179dfd70ea0dff02d767 |
| parent | 4a0b037464ccdf7bc090286f229dfad500a8ad23 |
Fixes #109558 files changed, 95 insertions(+), 6 deletions(-)
lib/std/zig/c_translation.zig+6| ... | @@ -30,6 +30,12 @@ pub fn cast(comptime DestType: type, target: anytype) DestType { | ... | @@ -30,6 +30,12 @@ pub fn cast(comptime DestType: type, target: anytype) DestType { |
| 30 | else => {}, | 30 | else => {}, |
| 31 | } | 31 | } |
| 32 | }, | 32 | }, |
| 33 | .Union => |info| { | ||
| 34 | inline for (info.fields) |field| { | ||
| 35 | if (field.field_type == SourceType) return @unionInit(DestType, field.name, target); | ||
| 36 | } | ||
| 37 | @compileError("cast to union type '" ++ @typeName(DestType) ++ "' from type '" ++ @typeName(SourceType) ++ "' which is not present in union"); | ||
| 38 | }, | ||
| 33 | else => {}, | 39 | else => {}, |
| 34 | } | 40 | } |
| 35 | return @as(DestType, target); | 41 | return @as(DestType, target); |
src/clang.zig+8| ... | @@ -258,6 +258,14 @@ pub const CaseStmt = opaque { | ... | @@ -258,6 +258,14 @@ pub const CaseStmt = opaque { |
| 258 | extern fn ZigClangCaseStmt_getSubStmt(*const CaseStmt) *const Stmt; | 258 | extern fn ZigClangCaseStmt_getSubStmt(*const CaseStmt) *const Stmt; |
| 259 | }; | 259 | }; |
| 260 | 260 | ||
| 261 | pub const CastExpr = opaque { | ||
| 262 | pub const getCastKind = ZigClangCastExpr_getCastKind; | ||
| 263 | extern fn ZigClangCastExpr_getCastKind(*const CastExpr) CK; | ||
| 264 | |||
| 265 | pub const getTargetFieldForToUnionCast = ZigClangCastExpr_getTargetFieldForToUnionCast; | ||
| 266 | extern fn ZigClangCastExpr_getTargetFieldForToUnionCast(*const CastExpr, QualType, QualType) ?*const FieldDecl; | ||
| 267 | }; | ||
| 268 | |||
| 261 | pub const CharacterLiteral = opaque { | 269 | pub const CharacterLiteral = opaque { |
| 262 | pub const getBeginLoc = ZigClangCharacterLiteral_getBeginLoc; | 270 | pub const getBeginLoc = ZigClangCharacterLiteral_getBeginLoc; |
| 263 | extern fn ZigClangCharacterLiteral_getBeginLoc(*const CharacterLiteral) SourceLocation; | 271 | extern fn ZigClangCharacterLiteral_getBeginLoc(*const CharacterLiteral) SourceLocation; |
src/translate_c.zig+23-6| ... | @@ -1791,14 +1791,31 @@ fn transCStyleCastExprClass( | ... | @@ -1791,14 +1791,31 @@ fn transCStyleCastExprClass( |
| 1791 | stmt: *const clang.CStyleCastExpr, | 1791 | stmt: *const clang.CStyleCastExpr, |
| 1792 | result_used: ResultUsed, | 1792 | result_used: ResultUsed, |
| 1793 | ) TransError!Node { | 1793 | ) TransError!Node { |
| 1794 | const cast_expr = @ptrCast(*const clang.CastExpr, stmt); | ||
| 1794 | const sub_expr = stmt.getSubExpr(); | 1795 | const sub_expr = stmt.getSubExpr(); |
| 1795 | const cast_node = (try transCCast( | 1796 | const dst_type = stmt.getType(); |
| 1797 | const src_type = sub_expr.getType(); | ||
| 1798 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used); | ||
| 1799 | const loc = stmt.getBeginLoc(); | ||
| 1800 | |||
| 1801 | const cast_node = if (cast_expr.getCastKind() == .ToUnion) blk: { | ||
| 1802 | const field_decl = cast_expr.getTargetFieldForToUnionCast(dst_type, src_type).?; // C syntax error if target field is null | ||
| 1803 | const field_name = try c.str(@ptrCast(*const clang.NamedDecl, field_decl).getName_bytes_begin()); | ||
| 1804 | |||
| 1805 | const union_ty = try transQualType(c, scope, dst_type, loc); | ||
| 1806 | |||
| 1807 | const inits = [1]ast.Payload.ContainerInit.Initializer{.{ .name = field_name, .value = sub_expr_node }}; | ||
| 1808 | break :blk try Tag.container_init.create(c.arena, .{ | ||
| 1809 | .lhs = union_ty, | ||
| 1810 | .inits = try c.arena.dupe(ast.Payload.ContainerInit.Initializer, &inits), | ||
| 1811 | }); | ||
| 1812 | } else (try transCCast( | ||
| 1796 | c, | 1813 | c, |
| 1797 | scope, | 1814 | scope, |
| 1798 | stmt.getBeginLoc(), | 1815 | loc, |
| 1799 | stmt.getType(), | 1816 | dst_type, |
| 1800 | sub_expr.getType(), | 1817 | src_type, |
| 1801 | try transExpr(c, scope, sub_expr, .used), | 1818 | sub_expr_node, |
| 1802 | )); | 1819 | )); |
| 1803 | return maybeSuppressResult(c, scope, result_used, cast_node); | 1820 | return maybeSuppressResult(c, scope, result_used, cast_node); |
| 1804 | } | 1821 | } |
| ... | @@ -2370,7 +2387,7 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType { | ... | @@ -2370,7 +2387,7 @@ fn cIntTypeForEnum(enum_qt: clang.QualType) clang.QualType { |
| 2370 | return enum_decl.getIntegerType(); | 2387 | return enum_decl.getIntegerType(); |
| 2371 | } | 2388 | } |
| 2372 | 2389 | ||
| 2373 | // when modifying this function, make sure to also update std.meta.cast | 2390 | // when modifying this function, make sure to also update std.zig.c_translation.cast |
| 2374 | fn transCCast( | 2391 | fn transCCast( |
| 2375 | c: *Context, | 2392 | c: *Context, |
| 2376 | scope: *Scope, | 2393 | scope: *Scope, |
src/zig_clang.cpp+12| ... | @@ -2986,6 +2986,18 @@ const struct ZigClangCompoundStmt *ZigClangStmtExpr_getSubStmt(const struct ZigC | ... | @@ -2986,6 +2986,18 @@ const struct ZigClangCompoundStmt *ZigClangStmtExpr_getSubStmt(const struct ZigC |
| 2986 | return reinterpret_cast<const ZigClangCompoundStmt *>(casted->getSubStmt()); | 2986 | return reinterpret_cast<const ZigClangCompoundStmt *>(casted->getSubStmt()); |
| 2987 | } | 2987 | } |
| 2988 | 2988 | ||
| 2989 | enum ZigClangCK ZigClangCastExpr_getCastKind(const struct ZigClangCastExpr *self) { | ||
| 2990 | auto casted = reinterpret_cast<const clang::CastExpr *>(self); | ||
| 2991 | return (ZigClangCK)casted->getCastKind(); | ||
| 2992 | } | ||
| 2993 | |||
| 2994 | const struct ZigClangFieldDecl *ZigClangCastExpr_getTargetFieldForToUnionCast(const struct ZigClangCastExpr *self, ZigClangQualType union_type, ZigClangQualType op_type) { | ||
| 2995 | clang::QualType union_qt = bitcast(union_type); | ||
| 2996 | clang::QualType op_qt = bitcast(op_type); | ||
| 2997 | auto casted = reinterpret_cast<const clang::CastExpr *>(self); | ||
| 2998 | return reinterpret_cast<const ZigClangFieldDecl *>(casted->getTargetFieldForToUnionCast(union_qt, op_qt)); | ||
| 2999 | } | ||
| 3000 | |||
| 2989 | struct ZigClangSourceLocation ZigClangCharacterLiteral_getBeginLoc(const struct ZigClangCharacterLiteral *self) { | 3001 | struct ZigClangSourceLocation ZigClangCharacterLiteral_getBeginLoc(const struct ZigClangCharacterLiteral *self) { |
| 2990 | auto casted = reinterpret_cast<const clang::CharacterLiteral *>(self); | 3002 | auto casted = reinterpret_cast<const clang::CharacterLiteral *>(self); |
| 2991 | return bitcast(casted->getBeginLoc()); | 3003 | return bitcast(casted->getBeginLoc()); |
src/zig_clang.h+4| ... | @@ -103,6 +103,7 @@ struct ZigClangBuiltinType; | ... | @@ -103,6 +103,7 @@ struct ZigClangBuiltinType; |
| 103 | struct ZigClangCStyleCastExpr; | 103 | struct ZigClangCStyleCastExpr; |
| 104 | struct ZigClangCallExpr; | 104 | struct ZigClangCallExpr; |
| 105 | struct ZigClangCaseStmt; | 105 | struct ZigClangCaseStmt; |
| 106 | struct ZigClangCastExpr; | ||
| 106 | struct ZigClangCharacterLiteral; | 107 | struct ZigClangCharacterLiteral; |
| 107 | struct ZigClangChooseExpr; | 108 | struct ZigClangChooseExpr; |
| 108 | struct ZigClangCompoundAssignOperator; | 109 | struct ZigClangCompoundAssignOperator; |
| ... | @@ -1317,6 +1318,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangDecayedType_getDecayedType(const st | ... | @@ -1317,6 +1318,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangDecayedType_getDecayedType(const st |
| 1317 | 1318 | ||
| 1318 | ZIG_EXTERN_C const struct ZigClangCompoundStmt *ZigClangStmtExpr_getSubStmt(const struct ZigClangStmtExpr *); | 1319 | ZIG_EXTERN_C const struct ZigClangCompoundStmt *ZigClangStmtExpr_getSubStmt(const struct ZigClangStmtExpr *); |
| 1319 | 1320 | ||
| 1321 | ZIG_EXTERN_C enum ZigClangCK ZigClangCastExpr_getCastKind(const struct ZigClangCastExpr *); | ||
| 1322 | ZIG_EXTERN_C const struct ZigClangFieldDecl *ZigClangCastExpr_getTargetFieldForToUnionCast(const struct ZigClangCastExpr *, struct ZigClangQualType, struct ZigClangQualType); | ||
| 1323 | |||
| 1320 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCharacterLiteral_getBeginLoc(const struct ZigClangCharacterLiteral *); | 1324 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangCharacterLiteral_getBeginLoc(const struct ZigClangCharacterLiteral *); |
| 1321 | ZIG_EXTERN_C enum ZigClangCharacterLiteral_CharacterKind ZigClangCharacterLiteral_getKind(const struct ZigClangCharacterLiteral *); | 1325 | ZIG_EXTERN_C enum ZigClangCharacterLiteral_CharacterKind ZigClangCharacterLiteral_getKind(const struct ZigClangCharacterLiteral *); |
| 1322 | ZIG_EXTERN_C unsigned ZigClangCharacterLiteral_getValue(const struct ZigClangCharacterLiteral *); | 1326 | ZIG_EXTERN_C unsigned ZigClangCharacterLiteral_getValue(const struct ZigClangCharacterLiteral *); |
test/behavior/translate_c_macros.h+7| ... | @@ -15,6 +15,11 @@ struct Foo { | ... | @@ -15,6 +15,11 @@ struct Foo { |
| 15 | int a; | 15 | int a; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | union U { | ||
| 19 | long l; | ||
| 20 | double d; | ||
| 21 | }; | ||
| 22 | |||
| 18 | #define SIZE_OF_FOO sizeof(struct Foo) | 23 | #define SIZE_OF_FOO sizeof(struct Foo) |
| 19 | 24 | ||
| 20 | #define MAP_FAILED	((void *) -1) | 25 | #define MAP_FAILED	((void *) -1) |
| ... | @@ -30,3 +35,5 @@ struct Foo { | ... | @@ -30,3 +35,5 @@ struct Foo { |
| 30 | #define IGNORE_ME_8(x) (volatile void)(x) | 35 | #define IGNORE_ME_8(x) (volatile void)(x) |
| 31 | #define IGNORE_ME_9(x) (const volatile void)(x) | 36 | #define IGNORE_ME_9(x) (const volatile void)(x) |
| 32 | #define IGNORE_ME_10(x) (volatile const void)(x) | 37 | #define IGNORE_ME_10(x) (volatile const void)(x) |
| 38 | |||
| 39 | #define UNION_CAST(X) (union U)(X) |
test/behavior/translate_c_macros.zig+13| ... | @@ -47,3 +47,16 @@ test "cast negative integer to pointer" { | ... | @@ -47,3 +47,16 @@ test "cast negative integer to pointer" { |
| 47 | 47 | ||
| 48 | try expectEqual(@intToPtr(?*anyopaque, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED); | 48 | try expectEqual(@intToPtr(?*anyopaque, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED); |
| 49 | } | 49 | } |
| 50 | |||
| 51 | test "casting to union with a macro" { | ||
| 52 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO Sema.zirUnionInitPtr | ||
| 53 | |||
| 54 | const l: c_long = 42; | ||
| 55 | const d: f64 = 2.0; | ||
| 56 | |||
| 57 | var casted = h.UNION_CAST(l); | ||
| 58 | try expectEqual(l, casted.l); | ||
| 59 | |||
| 60 | casted = h.UNION_CAST(d); | ||
| 61 | try expectEqual(d, casted.d); | ||
| 62 | } |
test/run_translated_c.zig+22| ... | @@ -1829,4 +1829,26 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { | ... | @@ -1829,4 +1829,26 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 1829 | \\ return 0; | 1829 | \\ return 0; |
| 1830 | \\} | 1830 | \\} |
| 1831 | , ""); | 1831 | , ""); |
| 1832 | |||
| 1833 | cases.add("Cast-to-union. Issue #10955", | ||
| 1834 | \\#include <stdlib.h> | ||
| 1835 | \\struct S { int x; }; | ||
| 1836 | \\union U { | ||
| 1837 | \\ long l; | ||
| 1838 | \\ double d; | ||
| 1839 | \\ struct S s; | ||
| 1840 | \\}; | ||
| 1841 | \\union U bar(union U u) { return u; } | ||
| 1842 | \\int main(void) { | ||
| 1843 | \\ union U u = (union U) 42L; | ||
| 1844 | \\ if (u.l != 42L) abort(); | ||
| 1845 | \\ u = (union U) 2.0; | ||
| 1846 | \\ if (u.d != 2.0) abort(); | ||
| 1847 | \\ u = bar((union U)4.0); | ||
| 1848 | \\ if (u.d != 4.0) abort(); | ||
| 1849 | \\ u = (union U)(struct S){ .x = 5 }; | ||
| 1850 | \\ if (u.s.x != 5) abort(); | ||
| 1851 | \\ return 0; | ||
| 1852 | \\} | ||
| 1853 | , ""); | ||
| 1832 | } | 1854 | } |