| author | |
| committer | |
| log | 578a792b33d1f26c839cd6c77eaa2680601caaf2 |
| tree | 1378c449be224c8b81fcb46ca4b1ad9097588c9b |
| parent | 3bfb1616db0883e6145a1fe1844eee3038bd4ca1 |
| parent | 101aac92c258af9f25520c36f06b2ce8335d7f9a |
| signature |
Make self hosted compiler capable of building itself12 files changed, 114 insertions(+), 38 deletions(-)
lib/std/c.zig+12-4| ... | ... | @@ -219,7 +219,11 @@ pub extern "c" fn utimes(path: [*:0]const u8, times: *[2]c.timeval) c_int; |
| 219 | 219 | pub extern "c" fn utimensat(dirfd: c.fd_t, pathname: [*:0]const u8, times: *[2]c.timespec, flags: u32) c_int; |
| 220 | 220 | pub extern "c" fn futimens(fd: c.fd_t, times: *const [2]c.timespec) c_int; |
| 221 | 221 | |
| 222 | pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const c.pthread_attr_t, start_routine: fn (?*anyopaque) callconv(.C) ?*anyopaque, noalias arg: ?*anyopaque) c.E; | |
| 222 | pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const c.pthread_attr_t, start_routine: PThreadStartFn, noalias arg: ?*anyopaque) c.E; | |
| 223 | const PThreadStartFn = if (builtin.zig_backend == .stage1) | |
| 224 | fn (?*anyopaque) callconv(.C) ?*anyopaque | |
| 225 | else | |
| 226 | *const fn (?*anyopaque) callconv(.C) ?*anyopaque; | |
| 223 | 227 | pub extern "c" fn pthread_attr_init(attr: *c.pthread_attr_t) c.E; |
| 224 | 228 | pub extern "c" fn pthread_attr_setstack(attr: *c.pthread_attr_t, stackaddr: *anyopaque, stacksize: usize) c.E; |
| 225 | 229 | pub extern "c" fn pthread_attr_setstacksize(attr: *c.pthread_attr_t, stacksize: usize) c.E; |
| ... | ... | @@ -229,10 +233,14 @@ pub extern "c" fn pthread_self() pthread_t; |
| 229 | 233 | pub extern "c" fn pthread_join(thread: pthread_t, arg_return: ?*?*anyopaque) c.E; |
| 230 | 234 | pub extern "c" fn pthread_detach(thread: pthread_t) c.E; |
| 231 | 235 | pub extern "c" fn pthread_atfork( |
| 232 | prepare: ?fn () callconv(.C) void, | |
| 233 | parent: ?fn () callconv(.C) void, | |
| 234 | child: ?fn () callconv(.C) void, | |
| 236 | prepare: ?PThreadForkFn, | |
| 237 | parent: ?PThreadForkFn, | |
| 238 | child: ?PThreadForkFn, | |
| 235 | 239 | ) c_int; |
| 240 | const PThreadForkFn = if (builtin.zig_backend == .stage1) | |
| 241 | fn () callconv(.C) void | |
| 242 | else | |
| 243 | *const fn () callconv(.C) void; | |
| 236 | 244 | pub extern "c" fn pthread_key_create(key: *c.pthread_key_t, destructor: ?fn (value: *anyopaque) callconv(.C) void) c.E; |
| 237 | 245 | pub extern "c" fn pthread_key_delete(key: c.pthread_key_t) c.E; |
| 238 | 246 | pub extern "c" fn pthread_getspecific(key: c.pthread_key_t) ?*anyopaque; |
lib/std/c/tokenizer.zig+5-1| ... | ... | @@ -126,7 +126,11 @@ pub const Token = struct { |
| 126 | 126 | Keyword_error, |
| 127 | 127 | Keyword_pragma, |
| 128 | 128 | |
| 129 | pub fn symbol(id: std.meta.Tag(Id)) []const u8 { | |
| 129 | pub fn symbol(id: Id) []const u8 { | |
| 130 | return symbolName(id); | |
| 131 | } | |
| 132 | ||
| 133 | pub fn symbolName(id: std.meta.Tag(Id)) []const u8 { | |
| 130 | 134 | return switch (id) { |
| 131 | 135 | .Invalid => "Invalid", |
| 132 | 136 | .Eof => "Eof", |
lib/std/special/c.zig+2-4| ... | ... | @@ -32,10 +32,8 @@ comptime { |
| 32 | 32 | @export(wasm_start, .{ .name = "_start", .linkage = .Strong }); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | if (builtin.zig_backend == .stage1) { // TODO remove this condition | |
| 36 | if (native_os == .linux) { | |
| 37 | @export(clone, .{ .name = "clone" }); | |
| 38 | } | |
| 35 | if (native_os == .linux) { | |
| 36 | @export(clone, .{ .name = "clone" }); | |
| 39 | 37 | } |
| 40 | 38 | |
| 41 | 39 | @export(memset, .{ .name = "memset", .linkage = .Strong }); |
src/AstGen.zig+13-14| ... | ... | @@ -1807,6 +1807,8 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1807 | 1807 | .@"break"; |
| 1808 | 1808 | |
| 1809 | 1809 | if (rhs == 0) { |
| 1810 | try genDefers(parent_gz, scope, parent_scope, .normal_only); | |
| 1811 | ||
| 1810 | 1812 | _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); |
| 1811 | 1813 | return Zir.Inst.Ref.unreachable_value; |
| 1812 | 1814 | } |
| ... | ... | @@ -1819,12 +1821,15 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1819 | 1821 | const prev_rvalue_noresult = parent_gz.rvalue_noresult; |
| 1820 | 1822 | parent_gz.rvalue_noresult = .none; |
| 1821 | 1823 | const operand = try reachableExpr(parent_gz, parent_scope, block_gz.break_result_loc, rhs, node); |
| 1824 | const search_index = @intCast(Zir.Inst.Index, astgen.instructions.len); | |
| 1822 | 1825 | parent_gz.rvalue_noresult = prev_rvalue_noresult; |
| 1823 | 1826 | |
| 1827 | try genDefers(parent_gz, scope, parent_scope, .normal_only); | |
| 1828 | ||
| 1824 | 1829 | switch (block_gz.break_result_loc) { |
| 1825 | 1830 | .block_ptr => { |
| 1826 | 1831 | const br = try parent_gz.addBreak(break_tag, block_inst, operand); |
| 1827 | try block_gz.labeled_breaks.append(astgen.gpa, br); | |
| 1832 | try block_gz.labeled_breaks.append(astgen.gpa, .{ .br = br, .search = search_index }); | |
| 1828 | 1833 | }, |
| 1829 | 1834 | .ptr => { |
| 1830 | 1835 | // In this case we don't have any mechanism to intercept it; |
| ... | ... | @@ -1843,13 +1848,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1843 | 1848 | .local_val => scope = scope.cast(Scope.LocalVal).?.parent, |
| 1844 | 1849 | .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent, |
| 1845 | 1850 | .namespace => break, |
| 1846 | .defer_normal => { | |
| 1847 | const defer_scope = scope.cast(Scope.Defer).?; | |
| 1848 | scope = defer_scope.parent; | |
| 1849 | const expr_node = node_datas[defer_scope.defer_node].rhs; | |
| 1850 | try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); | |
| 1851 | }, | |
| 1852 | .defer_error => scope = scope.cast(Scope.Defer).?.parent, | |
| 1851 | .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent, | |
| 1853 | 1852 | .top => unreachable, |
| 1854 | 1853 | } |
| 1855 | 1854 | } |
| ... | ... | @@ -2030,7 +2029,7 @@ fn labeledBlockExpr( |
| 2030 | 2029 | // The code took advantage of the result location as a pointer. |
| 2031 | 2030 | // Turn the break instruction operands into void. |
| 2032 | 2031 | for (block_scope.labeled_breaks.items) |br| { |
| 2033 | zir_datas[br].@"break".operand = .void_value; | |
| 2032 | zir_datas[br.br].@"break".operand = .void_value; | |
| 2034 | 2033 | } |
| 2035 | 2034 | try block_scope.setBlockBody(block_inst); |
| 2036 | 2035 | |
| ... | ... | @@ -2047,17 +2046,17 @@ fn labeledBlockExpr( |
| 2047 | 2046 | for (block_scope.labeled_breaks.items) |br| { |
| 2048 | 2047 | // We expect the `store_to_block_ptr` to be created between 1-3 instructions |
| 2049 | 2048 | // prior to the break. |
| 2050 | var search_index = br -| 3; | |
| 2051 | while (search_index < br) : (search_index += 1) { | |
| 2049 | var search_index = br.search -| 3; | |
| 2050 | while (search_index < br.search) : (search_index += 1) { | |
| 2052 | 2051 | if (zir_tags[search_index] == .store_to_block_ptr and |
| 2053 | 2052 | zir_datas[search_index].bin.lhs == block_scope.rl_ptr) |
| 2054 | 2053 | { |
| 2055 | 2054 | zir_tags[search_index] = .as; |
| 2056 | 2055 | zir_datas[search_index].bin = .{ |
| 2057 | 2056 | .lhs = block_scope.rl_ty_inst, |
| 2058 | .rhs = zir_datas[br].@"break".operand, | |
| 2057 | .rhs = zir_datas[br.br].@"break".operand, | |
| 2059 | 2058 | }; |
| 2060 | zir_datas[br].@"break".operand = indexToRef(search_index); | |
| 2059 | zir_datas[br.br].@"break".operand = indexToRef(search_index); | |
| 2061 | 2060 | break; |
| 2062 | 2061 | } |
| 2063 | 2062 | } else unreachable; |
| ... | ... | @@ -9719,7 +9718,7 @@ const GenZir = struct { |
| 9719 | 9718 | break_count: usize = 0, |
| 9720 | 9719 | /// Tracks `break :foo bar` instructions so they can possibly be elided later if |
| 9721 | 9720 | /// the labeled block ends up not needing a result location pointer. |
| 9722 | labeled_breaks: ArrayListUnmanaged(Zir.Inst.Index) = .{}, | |
| 9721 | labeled_breaks: ArrayListUnmanaged(struct { br: Zir.Inst.Index, search: Zir.Inst.Index }) = .{}, | |
| 9723 | 9722 | |
| 9724 | 9723 | suspend_node: Ast.Node.Index = 0, |
| 9725 | 9724 | nosuspend_node: Ast.Node.Index = 0, |
src/clang.zig+8-3| ... | ... | @@ -161,7 +161,12 @@ pub const ASTUnit = opaque { |
| 161 | 161 | extern fn ZigClangASTUnit_getSourceManager(*ASTUnit) *SourceManager; |
| 162 | 162 | |
| 163 | 163 | pub const visitLocalTopLevelDecls = ZigClangASTUnit_visitLocalTopLevelDecls; |
| 164 | extern fn ZigClangASTUnit_visitLocalTopLevelDecls(*ASTUnit, context: ?*anyopaque, Fn: ?fn (?*anyopaque, *const Decl) callconv(.C) bool) bool; | |
| 164 | extern fn ZigClangASTUnit_visitLocalTopLevelDecls(*ASTUnit, context: ?*anyopaque, Fn: ?VisitorFn) bool; | |
| 165 | ||
| 166 | const VisitorFn = if (@import("builtin").zig_backend == .stage1) | |
| 167 | fn (?*anyopaque, *const Decl) callconv(.C) bool | |
| 168 | else | |
| 169 | *const fn (?*anyopaque, *const Decl) callconv(.C) bool; | |
| 165 | 170 | |
| 166 | 171 | pub const getLocalPreprocessingEntities_begin = ZigClangASTUnit_getLocalPreprocessingEntities_begin; |
| 167 | 172 | extern fn ZigClangASTUnit_getLocalPreprocessingEntities_begin(*ASTUnit) PreprocessingRecord.iterator; |
| ... | ... | @@ -490,8 +495,8 @@ pub const FloatingLiteral = opaque { |
| 490 | 495 | pub const getValueAsApproximateDouble = ZigClangFloatingLiteral_getValueAsApproximateDouble; |
| 491 | 496 | extern fn ZigClangFloatingLiteral_getValueAsApproximateDouble(*const FloatingLiteral) f64; |
| 492 | 497 | |
| 493 | pub const getBeginLoc = ZigClangIntegerLiteral_getBeginLoc; | |
| 494 | extern fn ZigClangIntegerLiteral_getBeginLoc(*const FloatingLiteral) SourceLocation; | |
| 498 | pub const getBeginLoc = ZigClangFloatingLiteral_getBeginLoc; | |
| 499 | extern fn ZigClangFloatingLiteral_getBeginLoc(*const FloatingLiteral) SourceLocation; | |
| 495 | 500 | |
| 496 | 501 | pub const getRawSemantics = ZigClangFloatingLiteral_getRawSemantics; |
| 497 | 502 | extern fn ZigClangFloatingLiteral_getRawSemantics(*const FloatingLiteral) APFloatBaseSemantics; |
src/codegen/llvm.zig+21-6| ... | ... | @@ -4732,10 +4732,11 @@ pub const FuncGen = struct { |
| 4732 | 4732 | var buf: Type.Payload.ElemType = undefined; |
| 4733 | 4733 | const payload_ty = optional_ty.optionalChild(&buf); |
| 4734 | 4734 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 4735 | const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; | |
| 4735 | 4736 | if (invert) { |
| 4736 | return self.builder.buildNot(operand, ""); | |
| 4737 | return self.builder.buildNot(loaded, ""); | |
| 4737 | 4738 | } else { |
| 4738 | return operand; | |
| 4739 | return loaded; | |
| 4739 | 4740 | } |
| 4740 | 4741 | } |
| 4741 | 4742 | |
| ... | ... | @@ -4784,12 +4785,16 @@ pub const FuncGen = struct { |
| 4784 | 4785 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4785 | 4786 | const operand = try self.resolveInst(ty_op.operand); |
| 4786 | 4787 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); |
| 4788 | const result_ty = self.air.getRefType(ty_op.ty); | |
| 4787 | 4789 | var buf: Type.Payload.ElemType = undefined; |
| 4788 | 4790 | const payload_ty = optional_ty.optionalChild(&buf); |
| 4789 | 4791 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 4790 | 4792 | // We have a pointer to a zero-bit value and we need to return |
| 4791 | 4793 | // a pointer to a zero-bit value. |
| 4792 | return operand; | |
| 4794 | ||
| 4795 | // TODO once we update to LLVM 14 this bitcast won't be necessary. | |
| 4796 | const res_ptr_ty = try self.dg.llvmType(result_ty); | |
| 4797 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); | |
| 4793 | 4798 | } |
| 4794 | 4799 | if (optional_ty.isPtrLikeOptional()) { |
| 4795 | 4800 | // The payload and the optional are the same value. |
| ... | ... | @@ -4807,13 +4812,17 @@ pub const FuncGen = struct { |
| 4807 | 4812 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4808 | 4813 | const operand = try self.resolveInst(ty_op.operand); |
| 4809 | 4814 | const optional_ty = self.air.typeOf(ty_op.operand).childType(); |
| 4815 | const result_ty = self.air.getRefType(ty_op.ty); | |
| 4810 | 4816 | var buf: Type.Payload.ElemType = undefined; |
| 4811 | 4817 | const payload_ty = optional_ty.optionalChild(&buf); |
| 4812 | 4818 | const non_null_bit = self.context.intType(1).constAllOnes(); |
| 4813 | 4819 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 4814 | 4820 | // We have a pointer to a i1. We need to set it to 1 and then return the same pointer. |
| 4815 | 4821 | _ = self.builder.buildStore(non_null_bit, operand); |
| 4816 | return operand; | |
| 4822 | ||
| 4823 | // TODO once we update to LLVM 14 this bitcast won't be necessary. | |
| 4824 | const res_ptr_ty = try self.dg.llvmType(result_ty); | |
| 4825 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); | |
| 4817 | 4826 | } |
| 4818 | 4827 | if (optional_ty.isPtrLikeOptional()) { |
| 4819 | 4828 | // The payload and the optional are the same value. |
| ... | ... | @@ -4872,7 +4881,13 @@ pub const FuncGen = struct { |
| 4872 | 4881 | const target = self.dg.module.getTarget(); |
| 4873 | 4882 | const offset: u8 = if (payload_ty.abiAlignment(target) > Type.anyerror.abiSize(target)) 2 else 1; |
| 4874 | 4883 | |
| 4875 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null; | |
| 4884 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { | |
| 4885 | if (!operand_is_ptr) return null; | |
| 4886 | ||
| 4887 | // TODO once we update to LLVM 14 this bitcast won't be necessary. | |
| 4888 | const res_ptr_ty = try self.dg.llvmType(result_ty); | |
| 4889 | return self.builder.buildBitCast(operand, res_ptr_ty, ""); | |
| 4890 | } | |
| 4876 | 4891 | if (operand_is_ptr or isByRef(payload_ty)) { |
| 4877 | 4892 | return self.builder.buildStructGEP(operand, offset, ""); |
| 4878 | 4893 | } |
| ... | ... | @@ -7205,7 +7220,7 @@ pub const FuncGen = struct { |
| 7205 | 7220 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); |
| 7206 | 7221 | } |
| 7207 | 7222 | |
| 7208 | fn getIntrinsic(self: *FuncGen, name: []const u8, types: []*const llvm.Type) *const llvm.Value { | |
| 7223 | fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value { | |
| 7209 | 7224 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); |
| 7210 | 7225 | assert(id != 0); |
| 7211 | 7226 | return self.llvmModule().getIntrinsicDeclaration(id, types.ptr, types.len); |
src/codegen/llvm/bindings.zig+2-2| ... | ... | @@ -60,7 +60,7 @@ pub const Context = opaque { |
| 60 | 60 | Packed: Bool, |
| 61 | 61 | ) *const Type; |
| 62 | 62 | |
| 63 | const structCreateNamed = LLVMStructCreateNamed; | |
| 63 | pub const structCreateNamed = LLVMStructCreateNamed; | |
| 64 | 64 | extern fn LLVMStructCreateNamed(C: *const Context, Name: [*:0]const u8) *const Type; |
| 65 | 65 | |
| 66 | 66 | pub const constString = LLVMConstStringInContext; |
| ... | ... | @@ -320,7 +320,7 @@ pub const Module = opaque { |
| 320 | 320 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; |
| 321 | 321 | |
| 322 | 322 | pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration; |
| 323 | extern fn LLVMGetIntrinsicDeclaration(Mod: *const Module, ID: c_uint, ParamTypes: ?[*]*const Type, ParamCount: usize) *const Value; | |
| 323 | extern fn LLVMGetIntrinsicDeclaration(Mod: *const Module, ID: c_uint, ParamTypes: ?[*]const *const Type, ParamCount: usize) *const Value; | |
| 324 | 324 | |
| 325 | 325 | pub const printToString = LLVMPrintModuleToString; |
| 326 | 326 | extern fn LLVMPrintModuleToString(*const Module) [*:0]const u8; |
src/translate_c.zig+5-3| ... | ... | @@ -368,11 +368,13 @@ pub fn translate( |
| 368 | 368 | resources_path: [*:0]const u8, |
| 369 | 369 | zig_is_stage1: bool, |
| 370 | 370 | ) !std.zig.Ast { |
| 371 | // TODO stage2 bug | |
| 372 | var tmp = errors; | |
| 371 | 373 | const ast_unit = clang.LoadFromCommandLine( |
| 372 | 374 | args_begin, |
| 373 | 375 | args_end, |
| 374 | &errors.ptr, | |
| 375 | &errors.len, | |
| 376 | &tmp.ptr, | |
| 377 | &tmp.len, | |
| 376 | 378 | resources_path, |
| 377 | 379 | ) orelse { |
| 378 | 380 | if (errors.len == 0) return error.ASTUnitFailure; |
| ... | ... | @@ -5325,7 +5327,7 @@ const MacroCtx = struct { |
| 5325 | 5327 | try self.fail( |
| 5326 | 5328 | c, |
| 5327 | 5329 | "unable to translate C expr: expected '{s}' instead got '{s}'", |
| 5328 | .{ CToken.Id.symbol(expected_id), next_id.symbol() }, | |
| 5330 | .{ CToken.Id.symbolName(expected_id), next_id.symbol() }, | |
| 5329 | 5331 | ); |
| 5330 | 5332 | return error.ParseError; |
| 5331 | 5333 | } |
src/translate_c/ast.zig+1-1| ... | ... | @@ -779,7 +779,7 @@ const TokenTag = std.zig.Token.Tag; |
| 779 | 779 | |
| 780 | 780 | const Context = struct { |
| 781 | 781 | gpa: Allocator, |
| 782 | buf: std.ArrayList(u8) = .{}, | |
| 782 | buf: std.ArrayList(u8), | |
| 783 | 783 | nodes: std.zig.Ast.NodeList = .{}, |
| 784 | 784 | extra_data: std.ArrayListUnmanaged(std.zig.Ast.Node.Index) = .{}, |
| 785 | 785 | tokens: std.zig.Ast.TokenList = .{}, |
src/zig_clang.cpp+5| ... | ... | @@ -2706,6 +2706,11 @@ double ZigClangFloatingLiteral_getValueAsApproximateDouble(const ZigClangFloatin |
| 2706 | 2706 | return casted->getValueAsApproximateDouble(); |
| 2707 | 2707 | } |
| 2708 | 2708 | |
| 2709 | struct ZigClangSourceLocation ZigClangFloatingLiteral_getBeginLoc(const struct ZigClangFloatingLiteral *self) { | |
| 2710 | auto casted = reinterpret_cast<const clang::FloatingLiteral *>(self); | |
| 2711 | return bitcast(casted->getBeginLoc()); | |
| 2712 | } | |
| 2713 | ||
| 2709 | 2714 | ZigClangAPFloatBase_Semantics ZigClangFloatingLiteral_getRawSemantics(const ZigClangFloatingLiteral *self) { |
| 2710 | 2715 | auto casted = reinterpret_cast<const clang::FloatingLiteral *>(self); |
| 2711 | 2716 | return static_cast<ZigClangAPFloatBase_Semantics>(casted->getRawSemantics()); |
src/zig_clang.h+1| ... | ... | @@ -1245,6 +1245,7 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDeclStmt_getBeginLoc(const st |
| 1245 | 1245 | ZIG_EXTERN_C unsigned ZigClangAPFloat_convertToHexString(const struct ZigClangAPFloat *self, char *DST, |
| 1246 | 1246 | unsigned HexDigits, bool UpperCase, enum ZigClangAPFloat_roundingMode RM); |
| 1247 | 1247 | ZIG_EXTERN_C double ZigClangFloatingLiteral_getValueAsApproximateDouble(const ZigClangFloatingLiteral *self); |
| 1248 | ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFloatingLiteral_getBeginLoc(const struct ZigClangFloatingLiteral *); | |
| 1248 | 1249 | ZIG_EXTERN_C ZigClangAPFloatBase_Semantics ZigClangFloatingLiteral_getRawSemantics(const ZigClangFloatingLiteral *self); |
| 1249 | 1250 | |
| 1250 | 1251 | ZIG_EXTERN_C enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self); |
test/behavior/optional.zig+39| ... | ... | @@ -332,3 +332,42 @@ test "array of optional unaligned types" { |
| 332 | 332 | i += 1; |
| 333 | 333 | try expect(Enum.three == values[i].?.Num); |
| 334 | 334 | } |
| 335 | ||
| 336 | test "optional pointer to zero bit optional payload" { | |
| 337 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 338 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 339 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 340 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 341 | ||
| 342 | const B = struct { | |
| 343 | fn foo(_: *@This()) void {} | |
| 344 | }; | |
| 345 | const A = struct { | |
| 346 | b: ?B = .{}, | |
| 347 | }; | |
| 348 | var a: A = .{}; | |
| 349 | var a_ptr = &a; | |
| 350 | if (a_ptr.b) |*some| { | |
| 351 | some.foo(); | |
| 352 | } | |
| 353 | } | |
| 354 | ||
| 355 | test "optional pointer to zero bit error union payload" { | |
| 356 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 357 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 358 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 359 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 360 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 361 | ||
| 362 | const B = struct { | |
| 363 | fn foo(_: *@This()) void {} | |
| 364 | }; | |
| 365 | const A = struct { | |
| 366 | b: anyerror!B = .{}, | |
| 367 | }; | |
| 368 | var a: A = .{}; | |
| 369 | var a_ptr = &a; | |
| 370 | if (a_ptr.b) |*some| { | |
| 371 | some.foo(); | |
| 372 | } else |_| {} | |
| 373 | } |