| author | |
| committer | |
| log | 9ca9819488db580241a93ded7b93a054de2db8af |
| tree | 8ec0a042513823c789ab28bcca6a004c2163e6f8 |
| parent | 7c8d9cfa40ab96aede2a7fe8ec9dce6f10bc910a |
| parent | 28a0583b844654bec108a456eb619efb2af201a1 |
| signature |
translate-c: correctly handle pointers to opaque demoted structs5 files changed, 169 insertions(+), 103 deletions(-)
src/codegen/c.zig+1-1| ... | ... | @@ -91,7 +91,7 @@ fn genArray(file: *C, decl: *Decl) !void { |
| 91 | 91 | if (tv.val.cast(Value.Payload.Bytes)) |payload| |
| 92 | 92 | if (tv.ty.sentinel()) |sentinel| |
| 93 | 93 | if (sentinel.toUnsignedInt() == 0) |
| 94 | // TODO: static by default | |
| 94 | // TODO: static by default | |
| 95 | 95 | try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }) |
| 96 | 96 | else |
| 97 | 97 | return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{}) |
src/translate_c.zig+82-35| ... | ... | @@ -19,8 +19,6 @@ pub const Error = error{OutOfMemory}; |
| 19 | 19 | const TypeError = Error || error{UnsupportedType}; |
| 20 | 20 | const TransError = TypeError || error{UnsupportedTranslation}; |
| 21 | 21 | |
| 22 | const DeclTable = std.AutoArrayHashMap(usize, []const u8); | |
| 23 | ||
| 24 | 22 | const SymbolTable = std.StringArrayHashMap(*ast.Node); |
| 25 | 23 | const AliasList = std.ArrayList(struct { |
| 26 | 24 | alias: []const u8, |
| ... | ... | @@ -254,24 +252,25 @@ const Scope = struct { |
| 254 | 252 | pub const Context = struct { |
| 255 | 253 | gpa: *mem.Allocator, |
| 256 | 254 | arena: *mem.Allocator, |
| 257 | token_ids: std.ArrayListUnmanaged(Token.Id), | |
| 258 | token_locs: std.ArrayListUnmanaged(Token.Loc), | |
| 259 | errors: std.ArrayListUnmanaged(ast.Error), | |
| 255 | token_ids: std.ArrayListUnmanaged(Token.Id) = .{}, | |
| 256 | token_locs: std.ArrayListUnmanaged(Token.Loc) = .{}, | |
| 257 | errors: std.ArrayListUnmanaged(ast.Error) = .{}, | |
| 260 | 258 | source_buffer: *std.ArrayList(u8), |
| 261 | 259 | err: Error, |
| 262 | 260 | source_manager: *clang.SourceManager, |
| 263 | decl_table: DeclTable, | |
| 261 | decl_table: std.AutoArrayHashMapUnmanaged(usize, []const u8) = .{}, | |
| 264 | 262 | alias_list: AliasList, |
| 265 | 263 | global_scope: *Scope.Root, |
| 266 | 264 | clang_context: *clang.ASTContext, |
| 267 | 265 | mangle_count: u32 = 0, |
| 268 | root_decls: std.ArrayListUnmanaged(*ast.Node), | |
| 266 | root_decls: std.ArrayListUnmanaged(*ast.Node) = .{}, | |
| 267 | opaque_demotes: std.AutoHashMapUnmanaged(usize, void) = .{}, | |
| 269 | 268 | |
| 270 | 269 | /// This one is different than the root scope's name table. This contains |
| 271 | 270 | /// a list of names that we found by visiting all the top level decls without |
| 272 | 271 | /// translating them. The other maps are updated as we translate; this one is updated |
| 273 | 272 | /// up front in a pre-processing step. |
| 274 | global_names: std.StringArrayHashMap(void), | |
| 273 | global_names: std.StringArrayHashMapUnmanaged(void) = .{}, | |
| 275 | 274 | |
| 276 | 275 | fn getMangle(c: *Context) u32 { |
| 277 | 276 | c.mangle_count += 1; |
| ... | ... | @@ -362,24 +361,21 @@ pub fn translate( |
| 362 | 361 | .source_buffer = &source_buffer, |
| 363 | 362 | .source_manager = ast_unit.getSourceManager(), |
| 364 | 363 | .err = undefined, |
| 365 | .decl_table = DeclTable.init(gpa), | |
| 366 | 364 | .alias_list = AliasList.init(gpa), |
| 367 | 365 | .global_scope = try arena.allocator.create(Scope.Root), |
| 368 | 366 | .clang_context = ast_unit.getASTContext(), |
| 369 | .global_names = std.StringArrayHashMap(void).init(gpa), | |
| 370 | .token_ids = .{}, | |
| 371 | .token_locs = .{}, | |
| 372 | .errors = .{}, | |
| 373 | .root_decls = .{}, | |
| 374 | 367 | }; |
| 375 | 368 | context.global_scope.* = Scope.Root.init(&context); |
| 376 | defer context.decl_table.deinit(); | |
| 377 | defer context.alias_list.deinit(); | |
| 378 | defer context.token_ids.deinit(gpa); | |
| 379 | defer context.token_locs.deinit(gpa); | |
| 380 | defer context.errors.deinit(gpa); | |
| 381 | defer context.global_names.deinit(); | |
| 382 | defer context.root_decls.deinit(gpa); | |
| 369 | defer { | |
| 370 | context.decl_table.deinit(gpa); | |
| 371 | context.alias_list.deinit(); | |
| 372 | context.token_ids.deinit(gpa); | |
| 373 | context.token_locs.deinit(gpa); | |
| 374 | context.errors.deinit(gpa); | |
| 375 | context.global_names.deinit(gpa); | |
| 376 | context.root_decls.deinit(gpa); | |
| 377 | context.opaque_demotes.deinit(gpa); | |
| 378 | } | |
| 383 | 379 | |
| 384 | 380 | try prepopulateGlobalNameTable(ast_unit, &context); |
| 385 | 381 | |
| ... | ... | @@ -437,7 +433,7 @@ fn prepopulateGlobalNameTable(ast_unit: *clang.ASTUnit, c: *Context) !void { |
| 437 | 433 | const macro = @ptrCast(*clang.MacroDefinitionRecord, entity); |
| 438 | 434 | const raw_name = macro.getName_getNameStart(); |
| 439 | 435 | const name = try c.str(raw_name); |
| 440 | _ = try c.global_names.put(name, {}); | |
| 436 | _ = try c.global_names.put(c.gpa, name, {}); | |
| 441 | 437 | }, |
| 442 | 438 | else => {}, |
| 443 | 439 | } |
| ... | ... | @@ -465,7 +461,7 @@ fn declVisitorC(context: ?*c_void, decl: *const clang.Decl) callconv(.C) bool { |
| 465 | 461 | fn declVisitorNamesOnly(c: *Context, decl: *const clang.Decl) Error!void { |
| 466 | 462 | if (decl.castToNamedDecl()) |named_decl| { |
| 467 | 463 | const decl_name = try c.str(named_decl.getName_bytes_begin()); |
| 468 | _ = try c.global_names.put(decl_name, {}); | |
| 464 | _ = try c.global_names.put(c.gpa, decl_name, {}); | |
| 469 | 465 | } |
| 470 | 466 | } |
| 471 | 467 | |
| ... | ... | @@ -804,7 +800,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 804 | 800 | } |
| 805 | 801 | |
| 806 | 802 | fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const clang.TypedefNameDecl, builtin_name: []const u8) !*ast.Node { |
| 807 | _ = try c.decl_table.put(@ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name); | |
| 803 | _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), builtin_name); | |
| 808 | 804 | return transCreateNodeIdentifier(c, builtin_name); |
| 809 | 805 | } |
| 810 | 806 | |
| ... | ... | @@ -851,7 +847,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const clang.TypedefNameDecl, top_lev |
| 851 | 847 | return transCreateNodeIdentifier(c, checked_name); |
| 852 | 848 | } |
| 853 | 849 | |
| 854 | _ = try c.decl_table.put(@ptrToInt(typedef_decl.getCanonicalDecl()), checked_name); | |
| 850 | _ = try c.decl_table.put(c.gpa, @ptrToInt(typedef_decl.getCanonicalDecl()), checked_name); | |
| 855 | 851 | const node = (try transCreateNodeTypedef(rp, typedef_decl, true, checked_name)) orelse return null; |
| 856 | 852 | try addTopLevelDecl(c, checked_name, node); |
| 857 | 853 | return transCreateNodeIdentifier(c, checked_name); |
| ... | ... | @@ -918,7 +914,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 918 | 914 | } |
| 919 | 915 | |
| 920 | 916 | const name = try std.fmt.allocPrint(c.arena, "{}_{}", .{ container_kind_name, bare_name }); |
| 921 | _ = try c.decl_table.put(@ptrToInt(record_decl.getCanonicalDecl()), name); | |
| 917 | _ = try c.decl_table.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), name); | |
| 922 | 918 | |
| 923 | 919 | const visib_tok = if (!is_unnamed) try appendToken(c, .Keyword_pub, "pub") else null; |
| 924 | 920 | const mut_tok = try appendToken(c, .Keyword_const, "const"); |
| ... | ... | @@ -930,6 +926,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 930 | 926 | const init_node = blk: { |
| 931 | 927 | const rp = makeRestorePoint(c); |
| 932 | 928 | const record_def = record_decl.getDefinition() orelse { |
| 929 | _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {}); | |
| 933 | 930 | const opaque_type = try transCreateNodeOpaqueType(c); |
| 934 | 931 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 935 | 932 | break :blk opaque_type; |
| ... | ... | @@ -954,6 +951,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 954 | 951 | const field_qt = field_decl.getType(); |
| 955 | 952 | |
| 956 | 953 | if (field_decl.isBitField()) { |
| 954 | _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {}); | |
| 957 | 955 | const opaque_type = try transCreateNodeOpaqueType(c); |
| 958 | 956 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 959 | 957 | try emitWarning(c, field_loc, "{} demoted to opaque type - has bitfield", .{container_kind_name}); |
| ... | ... | @@ -961,6 +959,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 961 | 959 | } |
| 962 | 960 | |
| 963 | 961 | if (qualTypeCanon(field_qt).isIncompleteOrZeroLengthArrayType(c.clang_context)) { |
| 962 | _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {}); | |
| 964 | 963 | const opaque_type = try transCreateNodeOpaqueType(c); |
| 965 | 964 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 966 | 965 | try emitWarning(c, field_loc, "{} demoted to opaque type - has variable length array", .{container_kind_name}); |
| ... | ... | @@ -979,6 +978,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 979 | 978 | _ = try appendToken(c, .Colon, ":"); |
| 980 | 979 | const field_type = transQualType(rp, field_qt, field_loc) catch |err| switch (err) { |
| 981 | 980 | error.UnsupportedType => { |
| 981 | _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(record_decl.getCanonicalDecl()), {}); | |
| 982 | 982 | const opaque_type = try transCreateNodeOpaqueType(c); |
| 983 | 983 | semicolon = try appendToken(c, .Semicolon, ";"); |
| 984 | 984 | try emitWarning(c, record_loc, "{} demoted to opaque type - unable to translate type of field {}", .{ container_kind_name, raw_name }); |
| ... | ... | @@ -988,13 +988,13 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 988 | 988 | }; |
| 989 | 989 | |
| 990 | 990 | const align_expr = blk_2: { |
| 991 | const alignment = field_decl.getAlignedAttribute(rp.c.clang_context); | |
| 991 | const alignment = field_decl.getAlignedAttribute(c.clang_context); | |
| 992 | 992 | if (alignment != 0) { |
| 993 | _ = try appendToken(rp.c, .Keyword_align, "align"); | |
| 994 | _ = try appendToken(rp.c, .LParen, "("); | |
| 993 | _ = try appendToken(c, .Keyword_align, "align"); | |
| 994 | _ = try appendToken(c, .LParen, "("); | |
| 995 | 995 | // Clang reports the alignment in bits |
| 996 | const expr = try transCreateNodeInt(rp.c, alignment / 8); | |
| 997 | _ = try appendToken(rp.c, .RParen, ")"); | |
| 996 | const expr = try transCreateNodeInt(c, alignment / 8); | |
| 997 | _ = try appendToken(c, .RParen, ")"); | |
| 998 | 998 | |
| 999 | 999 | break :blk_2 expr; |
| 1000 | 1000 | } |
| ... | ... | @@ -1013,6 +1013,7 @@ fn transRecordDecl(c: *Context, record_decl: *const clang.RecordDecl) Error!?*as |
| 1013 | 1013 | |
| 1014 | 1014 | if (is_anon) { |
| 1015 | 1015 | _ = try c.decl_table.put( |
| 1016 | c.gpa, | |
| 1016 | 1017 | @ptrToInt(field_decl.getCanonicalDecl()), |
| 1017 | 1018 | raw_name, |
| 1018 | 1019 | ); |
| ... | ... | @@ -1065,7 +1066,7 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node |
| 1065 | 1066 | } |
| 1066 | 1067 | |
| 1067 | 1068 | const name = try std.fmt.allocPrint(c.arena, "enum_{}", .{bare_name}); |
| 1068 | _ = try c.decl_table.put(@ptrToInt(enum_decl.getCanonicalDecl()), name); | |
| 1069 | _ = try c.decl_table.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), name); | |
| 1069 | 1070 | |
| 1070 | 1071 | const visib_tok = if (!is_unnamed) try appendToken(c, .Keyword_pub, "pub") else null; |
| 1071 | 1072 | const mut_tok = try appendToken(c, .Keyword_const, "const"); |
| ... | ... | @@ -1204,8 +1205,10 @@ fn transEnumDecl(c: *Context, enum_decl: *const clang.EnumDecl) Error!?*ast.Node |
| 1204 | 1205 | }; |
| 1205 | 1206 | mem.copy(*ast.Node, container_node.fieldsAndDecls(), fields_and_decls.items); |
| 1206 | 1207 | break :blk &container_node.base; |
| 1207 | } else | |
| 1208 | try transCreateNodeOpaqueType(c); | |
| 1208 | } else blk: { | |
| 1209 | _ = try c.opaque_demotes.put(c.gpa, @ptrToInt(enum_decl.getCanonicalDecl()), {}); | |
| 1210 | break :blk try transCreateNodeOpaqueType(c); | |
| 1211 | }; | |
| 1209 | 1212 | |
| 1210 | 1213 | const semicolon_token = try appendToken(c, .Semicolon, ";"); |
| 1211 | 1214 | const node = try ast.Node.VarDecl.create(c.arena, .{ |
| ... | ... | @@ -4767,7 +4770,7 @@ fn transType(rp: RestorePoint, ty: *const clang.Type, source_loc: clang.SourceLo |
| 4767 | 4770 | optional_node.rhs = try transQualType(rp, child_qt, source_loc); |
| 4768 | 4771 | return &optional_node.base; |
| 4769 | 4772 | } |
| 4770 | if (typeIsOpaque(rp.c, child_qt.getTypePtr(), source_loc)) { | |
| 4773 | if (typeIsOpaque(rp.c, child_qt.getTypePtr(), source_loc) or qualTypeWasDemotedToOpaque(rp.c, child_qt)) { | |
| 4771 | 4774 | const optional_node = try transCreateNodeSimplePrefixOp(rp.c, .OptionalType, .QuestionMark, "?"); |
| 4772 | 4775 | const pointer_node = try transCreateNodePtrType( |
| 4773 | 4776 | rp.c, |
| ... | ... | @@ -4853,6 +4856,50 @@ fn transType(rp: RestorePoint, ty: *const clang.Type, source_loc: clang.SourceLo |
| 4853 | 4856 | } |
| 4854 | 4857 | } |
| 4855 | 4858 | |
| 4859 | fn qualTypeWasDemotedToOpaque(c: *Context, qt: clang.QualType) bool { | |
| 4860 | const ty = qt.getTypePtr(); | |
| 4861 | switch (qt.getTypeClass()) { | |
| 4862 | .Typedef => { | |
| 4863 | const typedef_ty = @ptrCast(*const clang.TypedefType, ty); | |
| 4864 | ||
| 4865 | const typedef_decl = typedef_ty.getDecl(); | |
| 4866 | const underlying_type = typedef_decl.getUnderlyingType(); | |
| 4867 | return qualTypeWasDemotedToOpaque(c, underlying_type); | |
| 4868 | }, | |
| 4869 | .Record => { | |
| 4870 | const record_ty = @ptrCast(*const clang.RecordType, ty); | |
| 4871 | ||
| 4872 | const record_decl = record_ty.getDecl(); | |
| 4873 | const canonical = @ptrToInt(record_decl.getCanonicalDecl()); | |
| 4874 | return c.opaque_demotes.contains(canonical); | |
| 4875 | }, | |
| 4876 | .Enum => { | |
| 4877 | const enum_ty = @ptrCast(*const clang.EnumType, ty); | |
| 4878 | ||
| 4879 | const enum_decl = enum_ty.getDecl(); | |
| 4880 | const canonical = @ptrToInt(enum_decl.getCanonicalDecl()); | |
| 4881 | return c.opaque_demotes.contains(canonical); | |
| 4882 | }, | |
| 4883 | .Elaborated => { | |
| 4884 | const elaborated_ty = @ptrCast(*const clang.ElaboratedType, ty); | |
| 4885 | return qualTypeWasDemotedToOpaque(c, elaborated_ty.getNamedType()); | |
| 4886 | }, | |
| 4887 | .Decayed => { | |
| 4888 | const decayed_ty = @ptrCast(*const clang.DecayedType, ty); | |
| 4889 | return qualTypeWasDemotedToOpaque(c, decayed_ty.getDecayedType()); | |
| 4890 | }, | |
| 4891 | .Attributed => { | |
| 4892 | const attributed_ty = @ptrCast(*const clang.AttributedType, ty); | |
| 4893 | return qualTypeWasDemotedToOpaque(c, attributed_ty.getEquivalentType()); | |
| 4894 | }, | |
| 4895 | .MacroQualified => { | |
| 4896 | const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty); | |
| 4897 | return qualTypeWasDemotedToOpaque(c, macroqualified_ty.getModifiedType()); | |
| 4898 | }, | |
| 4899 | else => return false, | |
| 4900 | } | |
| 4901 | } | |
| 4902 | ||
| 4856 | 4903 | fn isCVoid(qt: clang.QualType) bool { |
| 4857 | 4904 | const ty = qt.getTypePtr(); |
| 4858 | 4905 | if (ty.getTypeClass() == .Builtin) { |
test/gen_h.zig+8-8| ... | ... | @@ -10,7 +10,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 10 | 10 | \\ B = 1, |
| 11 | 11 | \\ C = 2 |
| 12 | 12 | \\}; |
| 13 | , | |
| 13 | , | |
| 14 | 14 | \\void entry(enum Foo foo); |
| 15 | 15 | }); |
| 16 | 16 | |
| ... | ... | @@ -33,7 +33,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 33 | 33 | \\ uint64_t E; |
| 34 | 34 | \\ uint64_t F; |
| 35 | 35 | \\}; |
| 36 | , | |
| 36 | , | |
| 37 | 37 | \\void entry(struct Foo foo); |
| 38 | 38 | \\ |
| 39 | 39 | }); |
| ... | ... | @@ -68,7 +68,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 68 | 68 | \\ bool C; |
| 69 | 69 | \\ struct Big D; |
| 70 | 70 | \\}; |
| 71 | , | |
| 71 | , | |
| 72 | 72 | \\void entry(union Foo foo); |
| 73 | 73 | \\ |
| 74 | 74 | }); |
| ... | ... | @@ -79,7 +79,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 79 | 79 | \\export fn entry(foo: ?*Foo) void { } |
| 80 | 80 | , &[_][]const u8{ |
| 81 | 81 | \\struct Foo; |
| 82 | , | |
| 82 | , | |
| 83 | 83 | \\void entry(struct Foo * foo); |
| 84 | 84 | }); |
| 85 | 85 | |
| ... | ... | @@ -94,7 +94,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 94 | 94 | \\ int32_t A[2]; |
| 95 | 95 | \\ uint32_t * B[4]; |
| 96 | 96 | \\}; |
| 97 | , | |
| 97 | , | |
| 98 | 98 | \\void entry(struct Foo foo, uint8_t bar[]); |
| 99 | 99 | \\ |
| 100 | 100 | }); |
| ... | ... | @@ -109,7 +109,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 109 | 109 | \\} |
| 110 | 110 | , &[_][]const u8{ |
| 111 | 111 | \\struct S; |
| 112 | , | |
| 112 | , | |
| 113 | 113 | \\uint8_t a(struct S * s); |
| 114 | 114 | \\ |
| 115 | 115 | }); |
| ... | ... | @@ -125,7 +125,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 125 | 125 | \\} |
| 126 | 126 | , &[_][]const u8{ |
| 127 | 127 | \\union U; |
| 128 | , | |
| 128 | , | |
| 129 | 129 | \\uint8_t a(union U * s); |
| 130 | 130 | \\ |
| 131 | 131 | }); |
| ... | ... | @@ -141,7 +141,7 @@ pub fn addCases(cases: *tests.GenHContext) void { |
| 141 | 141 | \\} |
| 142 | 142 | , &[_][]const u8{ |
| 143 | 143 | \\enum E; |
| 144 | , | |
| 144 | , | |
| 145 | 145 | \\uint8_t a(enum E * s); |
| 146 | 146 | \\ |
| 147 | 147 | }); |
test/stage2/zir.zig+1-1| ... | ... | @@ -156,7 +156,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 156 | 156 | \\ %0 = call(@a, []) |
| 157 | 157 | \\ %1 = returnvoid() |
| 158 | 158 | \\}) |
| 159 | , | |
| 159 | , | |
| 160 | 160 | &[_][]const u8{ |
| 161 | 161 | ":18:21: error: message", |
| 162 | 162 | }, |
test/translate_c.zig+77-58| ... | ... | @@ -3,6 +3,26 @@ const std = @import("std"); |
| 3 | 3 | const CrossTarget = std.zig.CrossTarget; |
| 4 | 4 | |
| 5 | 5 | pub fn addCases(cases: *tests.TranslateCContext) void { |
| 6 | cases.add("pointer to opaque demoted struct", | |
| 7 | \\typedef struct { | |
| 8 | \\ _Atomic int foo; | |
| 9 | \\} Foo; | |
| 10 | \\ | |
| 11 | \\typedef struct { | |
| 12 | \\ Foo *bar; | |
| 13 | \\} Bar; | |
| 14 | , &[_][]const u8{ | |
| 15 | \\const struct_unnamed_1 = // | |
| 16 | , | |
| 17 | \\warning: unsupported type: 'Atomic' | |
| 18 | \\ opaque {}; // | |
| 19 | , | |
| 20 | \\pub const Foo = struct_unnamed_1; | |
| 21 | \\const struct_unnamed_2 = extern struct { | |
| 22 | \\ bar: ?*Foo, | |
| 23 | \\}; | |
| 24 | }); | |
| 25 | ||
| 6 | 26 | cases.add("macro expressions respect C operator precedence", |
| 7 | 27 | \\#define FOO *((foo) + 2) |
| 8 | 28 | \\#define VALUE (1 + 2 * 3 + 4 * 5 + 6 << 7 | 8 == 9) |
| ... | ... | @@ -11,9 +31,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 11 | 31 | \\ | (*((unsigned char *)(p) + 2) << 16)) |
| 12 | 32 | , &[_][]const u8{ |
| 13 | 33 | \\pub const FOO = (foo + 2).*; |
| 14 | , | |
| 34 | , | |
| 15 | 35 | \\pub const VALUE = ((((1 + (2 * 3)) + (4 * 5)) + 6) << 7) | @boolToInt(8 == 9); |
| 16 | , | |
| 36 | , | |
| 17 | 37 | \\pub inline fn _AL_READ3BYTES(p: anytype) @TypeOf(((@import("std").meta.cast([*c]u8, p)).* | (((@import("std").meta.cast([*c]u8, p)) + 1).* << 8)) | (((@import("std").meta.cast([*c]u8, p)) + 2).* << 16)) { |
| 18 | 38 | \\ return ((@import("std").meta.cast([*c]u8, p)).* | (((@import("std").meta.cast([*c]u8, p)) + 1).* << 8)) | (((@import("std").meta.cast([*c]u8, p)) + 2).* << 16); |
| 19 | 39 | \\} |
| ... | ... | @@ -81,11 +101,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 81 | 101 | \\ a: u8, |
| 82 | 102 | \\}; |
| 83 | 103 | \\pub const Color = struct_Color; |
| 84 | , | |
| 104 | , | |
| 85 | 105 | \\pub inline fn CLITERAL(type_1: anytype) @TypeOf(type_1) { |
| 86 | 106 | \\ return type_1; |
| 87 | 107 | \\} |
| 88 | , | |
| 108 | , | |
| 89 | 109 | \\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ 200, 200, 200, 255 }); |
| 90 | 110 | }); |
| 91 | 111 | |
| ... | ... | @@ -119,7 +139,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 119 | 139 | \\pub inline fn FOO(x: anytype) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) { |
| 120 | 140 | \\ return @boolToInt(x >= 0) + @boolToInt(x >= 0); |
| 121 | 141 | \\} |
| 122 | , | |
| 142 | , | |
| 123 | 143 | \\pub const BAR = (1 != 0) and (2 > 4); |
| 124 | 144 | }); |
| 125 | 145 | |
| ... | ... | @@ -138,7 +158,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 138 | 158 | \\struct bar { int x; int y[0]; }; |
| 139 | 159 | , &[_][]const u8{ |
| 140 | 160 | \\pub const struct_foo = opaque {}; |
| 141 | , | |
| 161 | , | |
| 142 | 162 | \\pub const struct_bar = opaque {}; |
| 143 | 163 | }); |
| 144 | 164 | |
| ... | ... | @@ -166,7 +186,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 166 | 186 | \\ _ = foo; |
| 167 | 187 | \\ break :blk bar; |
| 168 | 188 | \\}; |
| 169 | , | |
| 189 | , | |
| 170 | 190 | \\pub inline fn bar(x: anytype) @TypeOf(baz(1, 2)) { |
| 171 | 191 | \\ return blk: { |
| 172 | 192 | \\ _ = &x; |
| ... | ... | @@ -185,7 +205,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 185 | 205 | \\#define inline 2 |
| 186 | 206 | , &[_][]const u8{ |
| 187 | 207 | \\pub const foo = 1; |
| 188 | , | |
| 208 | , | |
| 189 | 209 | \\pub const @"inline" = 2; |
| 190 | 210 | }); |
| 191 | 211 | |
| ... | ... | @@ -205,12 +225,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 205 | 225 | \\}; |
| 206 | 226 | , &[_][]const u8{ |
| 207 | 227 | \\pub const struct_arcan_shmif_page = // |
| 208 | , | |
| 228 | , | |
| 209 | 229 | \\warning: unsupported type: 'Atomic' |
| 210 | 230 | \\ opaque {}; // |
| 211 | , | |
| 231 | , | |
| 212 | 232 | \\ warning: struct demoted to opaque type - unable to translate type of field abufused |
| 213 | , // TODO should be `addr: *struct_arcan_shmif_page` | |
| 233 | , // TODO should be `addr: *struct_arcan_shmif_page` | |
| 214 | 234 | \\pub const struct_arcan_shmif_cont = extern struct { |
| 215 | 235 | \\ addr: [*c]struct_arcan_shmif_page, |
| 216 | 236 | \\}; |
| ... | ... | @@ -529,7 +549,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 529 | 549 | \\Foo fun(Foo *a); |
| 530 | 550 | , &[_][]const u8{ |
| 531 | 551 | \\pub const Foo = c_void; |
| 532 | , | |
| 552 | , | |
| 533 | 553 | \\pub extern fn fun(a: ?*Foo) Foo; |
| 534 | 554 | }); |
| 535 | 555 | |
| ... | ... | @@ -629,7 +649,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 629 | 649 | \\}; |
| 630 | 650 | , &[_][]const u8{ |
| 631 | 651 | \\pub const struct_Foo = opaque {}; |
| 632 | , | |
| 652 | , | |
| 633 | 653 | \\pub const struct_Bar = extern struct { |
| 634 | 654 | \\ foo: ?*struct_Foo, |
| 635 | 655 | \\}; |
| ... | ... | @@ -646,7 +666,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 646 | 666 | \\#define FLASH_BANK_SIZE (FLASH_SIZE >> 1) /* 1 MB */ |
| 647 | 667 | , &[_][]const u8{ |
| 648 | 668 | \\pub const FLASH_SIZE = @as(c_ulong, 0x200000); |
| 649 | , | |
| 669 | , | |
| 650 | 670 | \\pub const FLASH_BANK_SIZE = FLASH_SIZE >> 1; |
| 651 | 671 | }); |
| 652 | 672 | |
| ... | ... | @@ -665,13 +685,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 665 | 685 | \\pub const struct_Foo = extern struct { |
| 666 | 686 | \\ a: [*c]Foo, |
| 667 | 687 | \\}; |
| 668 | , | |
| 688 | , | |
| 669 | 689 | \\pub const Foo = struct_Foo; |
| 670 | , | |
| 690 | , | |
| 671 | 691 | \\pub const struct_Bar = extern struct { |
| 672 | 692 | \\ a: [*c]Foo, |
| 673 | 693 | \\}; |
| 674 | , | |
| 694 | , | |
| 675 | 695 | \\pub const Bar = struct_Bar; |
| 676 | 696 | }); |
| 677 | 697 | |
| ... | ... | @@ -685,7 +705,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 685 | 705 | \\ x: c_int, |
| 686 | 706 | \\ y: [*c]u8, |
| 687 | 707 | \\}; |
| 688 | , | |
| 708 | , | |
| 689 | 709 | \\pub const Foo = struct_Foo; |
| 690 | 710 | }); |
| 691 | 711 | |
| ... | ... | @@ -697,7 +717,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 697 | 717 | \\pub const struct_Foo = extern struct { |
| 698 | 718 | \\ derp: ?fn ([*c]struct_Foo) callconv(.C) void, |
| 699 | 719 | \\}; |
| 700 | , | |
| 720 | , | |
| 701 | 721 | \\pub const Foo = struct_Foo; |
| 702 | 722 | }); |
| 703 | 723 | |
| ... | ... | @@ -706,9 +726,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 706 | 726 | \\struct Foo *some_func(struct Foo *foo, int x); |
| 707 | 727 | , &[_][]const u8{ |
| 708 | 728 | \\pub const struct_Foo = opaque {}; |
| 709 | , | |
| 729 | , | |
| 710 | 730 | \\pub extern fn some_func(foo: ?*struct_Foo, x: c_int) ?*struct_Foo; |
| 711 | , | |
| 731 | , | |
| 712 | 732 | \\pub const Foo = struct_Foo; |
| 713 | 733 | }); |
| 714 | 734 | |
| ... | ... | @@ -723,7 +743,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 723 | 743 | \\#define THING1 1234 |
| 724 | 744 | , &[_][]const u8{ |
| 725 | 745 | \\pub const THING1 = 1234; |
| 726 | , | |
| 746 | , | |
| 727 | 747 | \\pub const THING2 = THING1; |
| 728 | 748 | }); |
| 729 | 749 | |
| ... | ... | @@ -741,7 +761,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 741 | 761 | \\pub const struct_Bar = extern struct { |
| 742 | 762 | \\ next: [*c]struct_Foo, |
| 743 | 763 | \\}; |
| 744 | , | |
| 764 | , | |
| 745 | 765 | \\pub const struct_Foo = extern struct { |
| 746 | 766 | \\ next: [*c]struct_Bar, |
| 747 | 767 | \\}; |
| ... | ... | @@ -761,7 +781,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 761 | 781 | \\pub const struct_comptime = extern struct { |
| 762 | 782 | \\ @"defer": c_int, |
| 763 | 783 | \\}; |
| 764 | , | |
| 784 | , | |
| 765 | 785 | \\pub const @"comptime" = struct_comptime; |
| 766 | 786 | }); |
| 767 | 787 | |
| ... | ... | @@ -1003,7 +1023,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1003 | 1023 | \\ x: c_int, |
| 1004 | 1024 | \\ y: f64, |
| 1005 | 1025 | \\}; |
| 1006 | , | |
| 1026 | , | |
| 1007 | 1027 | \\pub const Foo = union_Foo; |
| 1008 | 1028 | }); |
| 1009 | 1029 | |
| ... | ... | @@ -1446,7 +1466,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1446 | 1466 | \\ p, |
| 1447 | 1467 | \\ _, |
| 1448 | 1468 | \\}; |
| 1449 | , | |
| 1469 | , | |
| 1450 | 1470 | \\pub const Baz = struct_Baz; |
| 1451 | 1471 | }); |
| 1452 | 1472 | |
| ... | ... | @@ -1512,13 +1532,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1512 | 1532 | \\#define bar fn_ptr2 |
| 1513 | 1533 | , &[_][]const u8{ |
| 1514 | 1534 | \\pub extern var fn_ptr: ?fn () callconv(.C) void; |
| 1515 | , | |
| 1535 | , | |
| 1516 | 1536 | \\pub inline fn foo() void { |
| 1517 | 1537 | \\ return fn_ptr.?(); |
| 1518 | 1538 | \\} |
| 1519 | , | |
| 1539 | , | |
| 1520 | 1540 | \\pub extern var fn_ptr2: ?fn (c_int, f32) callconv(.C) u8; |
| 1521 | , | |
| 1541 | , | |
| 1522 | 1542 | \\pub inline fn bar(arg_1: c_int, arg_2: f32) u8 { |
| 1523 | 1543 | \\ return fn_ptr2.?(arg_1, arg_2); |
| 1524 | 1544 | \\} |
| ... | ... | @@ -1549,13 +1569,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1549 | 1569 | \\ gl: struct_unnamed_1, |
| 1550 | 1570 | \\}; |
| 1551 | 1571 | \\pub extern var glProcs: union_OpenGLProcs; |
| 1552 | , | |
| 1572 | , | |
| 1553 | 1573 | \\pub const glClearPFN = PFNGLCLEARPROC; |
| 1554 | , | |
| 1574 | , | |
| 1555 | 1575 | \\pub inline fn glClearUnion(arg_2: GLbitfield) void { |
| 1556 | 1576 | \\ return glProcs.gl.Clear.?(arg_2); |
| 1557 | 1577 | \\} |
| 1558 | , | |
| 1578 | , | |
| 1559 | 1579 | \\pub const OpenGLProcs = union_OpenGLProcs; |
| 1560 | 1580 | }); |
| 1561 | 1581 | |
| ... | ... | @@ -1571,11 +1591,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1571 | 1591 | \\#define FOO(L,b) (L + b) |
| 1572 | 1592 | , &[_][]const u8{ |
| 1573 | 1593 | \\pub extern var c: c_int; |
| 1574 | , | |
| 1594 | , | |
| 1575 | 1595 | \\pub inline fn BASIC(c_1: anytype) @TypeOf(c_1 * 2) { |
| 1576 | 1596 | \\ return c_1 * 2; |
| 1577 | 1597 | \\} |
| 1578 | , | |
| 1598 | , | |
| 1579 | 1599 | \\pub inline fn FOO(L: anytype, b: anytype) @TypeOf(L + b) { |
| 1580 | 1600 | \\ return L + b; |
| 1581 | 1601 | \\} |
| ... | ... | @@ -1587,9 +1607,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1587 | 1607 | \\#define FOO_CHAR '\xfF' |
| 1588 | 1608 | , &[_][]const u8{ |
| 1589 | 1609 | \\pub const FOO = "aoeu\xab derp"; |
| 1590 | , | |
| 1610 | , | |
| 1591 | 1611 | \\pub const FOO2 = "aoeu\x7a derp"; |
| 1592 | , | |
| 1612 | , | |
| 1593 | 1613 | \\pub const FOO_CHAR = '\xff'; |
| 1594 | 1614 | }); |
| 1595 | 1615 | |
| ... | ... | @@ -1599,9 +1619,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1599 | 1619 | \\#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) |
| 1600 | 1620 | , &[_][]const u8{ |
| 1601 | 1621 | \\pub const PERIPH_BASE = @as(c_ulong, 0x40000000); |
| 1602 | , | |
| 1622 | , | |
| 1603 | 1623 | \\pub const D3_APB1PERIPH_BASE = PERIPH_BASE + @as(c_ulong, 0x18000000); |
| 1604 | , | |
| 1624 | , | |
| 1605 | 1625 | \\pub const RCC_BASE = D3_AHB1PERIPH_BASE + @as(c_ulong, 0x4400); |
| 1606 | 1626 | }); |
| 1607 | 1627 | |
| ... | ... | @@ -1738,7 +1758,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1738 | 1758 | , &[_][]const u8{ |
| 1739 | 1759 | \\pub export var anyerror_1: c_uint = @bitCast(c_uint, @as(c_int, 2)); |
| 1740 | 1760 | , |
| 1741 | ||
| 1742 | 1761 | \\pub const noreturn_2 = @compileError("unable to translate C expr: unexpected token .Keyword_noreturn"); |
| 1743 | 1762 | }); |
| 1744 | 1763 | |
| ... | ... | @@ -2011,7 +2030,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2011 | 2030 | \\ var p: c_int = @boolToInt(((c != null) and (td != 0))); |
| 2012 | 2031 | \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p); |
| 2013 | 2032 | \\} |
| 2014 | , | |
| 2033 | , | |
| 2015 | 2034 | \\pub const Foo = enum_Foo; |
| 2016 | 2035 | }); |
| 2017 | 2036 | |
| ... | ... | @@ -2030,14 +2049,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2030 | 2049 | \\ x: c_int, |
| 2031 | 2050 | \\ y: c_int, |
| 2032 | 2051 | \\}; |
| 2033 | , | |
| 2052 | , | |
| 2034 | 2053 | \\pub const enum_Bar = extern enum(c_int) { |
| 2035 | 2054 | \\ A, |
| 2036 | 2055 | \\ B, |
| 2037 | 2056 | \\ _, |
| 2038 | 2057 | \\}; |
| 2039 | 2058 | \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void; |
| 2040 | , | |
| 2059 | , | |
| 2041 | 2060 | \\pub const Foo = struct_Foo; |
| 2042 | 2061 | \\pub const Bar = enum_Bar; |
| 2043 | 2062 | }); |
| ... | ... | @@ -2153,9 +2172,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2153 | 2172 | \\ _ = a.b; |
| 2154 | 2173 | \\ _ = c.*.b; |
| 2155 | 2174 | \\} |
| 2156 | , | |
| 2175 | , | |
| 2157 | 2176 | \\pub const DOT = a.b; |
| 2158 | , | |
| 2177 | , | |
| 2159 | 2178 | \\pub const ARROW = a.*.b; |
| 2160 | 2179 | }); |
| 2161 | 2180 | |
| ... | ... | @@ -2171,7 +2190,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2171 | 2190 | \\ var index = arg_index; |
| 2172 | 2191 | \\ return array[@intCast(c_uint, index)]; |
| 2173 | 2192 | \\} |
| 2174 | , | |
| 2193 | , | |
| 2175 | 2194 | \\pub const ACCESS = array[2]; |
| 2176 | 2195 | }); |
| 2177 | 2196 | |
| ... | ... | @@ -2748,9 +2767,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2748 | 2767 | \\#define FOO_CHAR '\077' |
| 2749 | 2768 | , &[_][]const u8{ |
| 2750 | 2769 | \\pub const FOO = "aoeu\x13 derp"; |
| 2751 | , | |
| 2770 | , | |
| 2752 | 2771 | \\pub const FOO2 = "aoeu\x134 derp"; |
| 2753 | , | |
| 2772 | , | |
| 2754 | 2773 | \\pub const FOO_CHAR = '\x3f'; |
| 2755 | 2774 | }); |
| 2756 | 2775 | |
| ... | ... | @@ -2770,7 +2789,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2770 | 2789 | \\ @"1" = 6, |
| 2771 | 2790 | \\ _, |
| 2772 | 2791 | \\}; |
| 2773 | , | |
| 2792 | , | |
| 2774 | 2793 | \\pub const Foo = enum_Foo; |
| 2775 | 2794 | }); |
| 2776 | 2795 | |
| ... | ... | @@ -2782,9 +2801,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2782 | 2801 | \\pub inline fn FOO(bar: anytype) @TypeOf(baz((@import("std").meta.cast(?*c_void, baz)))) { |
| 2783 | 2802 | \\ return baz((@import("std").meta.cast(?*c_void, baz))); |
| 2784 | 2803 | \\} |
| 2785 | , | |
| 2804 | , | |
| 2786 | 2805 | \\pub const BAR = (@import("std").meta.cast(?*c_void, a)); |
| 2787 | , | |
| 2806 | , | |
| 2788 | 2807 | \\pub const BAZ = (@import("std").meta.cast(u32, 2)); |
| 2789 | 2808 | }); |
| 2790 | 2809 | |
| ... | ... | @@ -2824,7 +2843,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2824 | 2843 | \\pub inline fn MIN(a: anytype, b: anytype) @TypeOf(if (b < a) b else a) { |
| 2825 | 2844 | \\ return if (b < a) b else a; |
| 2826 | 2845 | \\} |
| 2827 | , | |
| 2846 | , | |
| 2828 | 2847 | \\pub inline fn MAX(a: anytype, b: anytype) @TypeOf(if (b > a) b else a) { |
| 2829 | 2848 | \\ return if (b > a) b else a; |
| 2830 | 2849 | \\} |
| ... | ... | @@ -2892,7 +2911,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2892 | 2911 | \\ var bar_1 = arg_bar_1; |
| 2893 | 2912 | \\ bar_1 = 2; |
| 2894 | 2913 | \\} |
| 2895 | , | |
| 2914 | , | |
| 2896 | 2915 | \\pub const bar = 4; |
| 2897 | 2916 | }); |
| 2898 | 2917 | |
| ... | ... | @@ -2964,9 +2983,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2964 | 2983 | \\#define BAZ "oh, " FOO |
| 2965 | 2984 | , &[_][]const u8{ |
| 2966 | 2985 | \\pub const FOO = "hello"; |
| 2967 | , | |
| 2986 | , | |
| 2968 | 2987 | \\pub const BAR = FOO ++ " world"; |
| 2969 | , | |
| 2988 | , | |
| 2970 | 2989 | \\pub const BAZ = "oh, " ++ FOO; |
| 2971 | 2990 | }); |
| 2972 | 2991 | |
| ... | ... | @@ -2976,9 +2995,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2976 | 2995 | \\#define BAR FOO BAZ |
| 2977 | 2996 | , &[_][]const u8{ |
| 2978 | 2997 | \\pub const FOO = "hello"; |
| 2979 | , | |
| 2998 | , | |
| 2980 | 2999 | \\pub const BAZ = " world"; |
| 2981 | , | |
| 3000 | , | |
| 2982 | 3001 | \\pub const BAR = FOO ++ BAZ; |
| 2983 | 3002 | }); |
| 2984 | 3003 | |
| ... | ... | @@ -2987,7 +3006,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2987 | 3006 | \\#define BAR FOO "c" |
| 2988 | 3007 | , &[_][]const u8{ |
| 2989 | 3008 | \\pub const FOO = "a" ++ "b"; |
| 2990 | , | |
| 3009 | , | |
| 2991 | 3010 | \\pub const BAR = FOO ++ "c"; |
| 2992 | 3011 | }); |
| 2993 | 3012 | |
| ... | ... | @@ -3023,7 +3042,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3023 | 3042 | \\#define FOO ((int)0x8000) |
| 3024 | 3043 | , &[_][]const u8{ |
| 3025 | 3044 | \\pub const NULL = (@import("std").meta.cast(?*c_void, 0)); |
| 3026 | , | |
| 3045 | , | |
| 3027 | 3046 | \\pub const FOO = (@import("std").meta.cast(c_int, 0x8000)); |
| 3028 | 3047 | }); |
| 3029 | 3048 |