diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/AstGen.zig | 9 | ||||
| -rw-r--r-- | src/Sema.zig | 62 | ||||
| -rw-r--r-- | src/codegen/c.zig | 14 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 30 | ||||
| -rw-r--r-- | src/translate_c.zig | 189 | ||||
| -rw-r--r-- | src/type.zig | 46 |
6 files changed, 171 insertions, 179 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index 07a972eaab..48e6a480f3 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -9709,7 +9709,7 @@ fn rvalue( const result_index = refToIndex(result) orelse return gz.addUnTok(.ref, result, src_token); const zir_tags = gz.astgen.instructions.items(.tag); - if (zir_tags[result_index].isParam()) + if (zir_tags[result_index].isParam() or astgen.isInferred(result)) return gz.addUnTok(.ref, result, src_token); const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index); if (!gop.found_existing) { @@ -12196,6 +12196,13 @@ fn isInferred(astgen: *AstGen, ref: Zir.Inst.Ref) bool { .alloc_inferred_comptime_mut, => true, + .extended => { + const zir_data = astgen.instructions.items(.data); + if (zir_data[inst].extended.opcode != .alloc) return false; + const small = @bitCast(Zir.Inst.AllocExtended.Small, zir_data[inst].extended.small); + return !small.has_type; + }, + else => false, }; } diff --git a/src/Sema.zig b/src/Sema.zig index 608d6d986a..9f425b7bcf 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5053,6 +5053,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro .label = &label, .inlining = parent_block.inlining, .is_comptime = parent_block.is_comptime, + .is_typeof = parent_block.is_typeof, .want_safety = parent_block.want_safety, .float_mode = parent_block.float_mode, .runtime_cond = parent_block.runtime_cond, @@ -5945,7 +5946,7 @@ fn zirCall( const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; if (backend_supports_error_return_tracing and sema.mod.comp.bin_file.options.error_return_tracing and - !block.is_comptime and (input_is_error or pop_error_return_trace)) + !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace)) { const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: { break :b try sema.analyzeCall(block, func, func_src, call_src, modifier, ensure_result_used, resolved_args, bound_arg_src); @@ -6425,7 +6426,7 @@ fn analyzeCall( } const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info); - if (!is_comptime_call) { + if (!is_comptime_call and !block.is_typeof) { try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin); const zir_tags = sema.code.instructions.items(.tag); @@ -6463,7 +6464,7 @@ fn analyzeCall( break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); }; - if (!is_comptime_call and sema.typeOf(result).zigTypeTag() != .NoReturn) { + if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag() != .NoReturn) { try sema.emitDbgInline( block, module_fn, @@ -6747,6 +6748,8 @@ fn analyzeGenericCallArg( try sema.queueFullTypeResolution(param_ty); runtime_args[runtime_i.*] = casted_arg; runtime_i.* += 1; + } else if (try sema.typeHasOnePossibleValue(block, arg_src, comptime_arg.ty)) |_| { + _ = try sema.coerce(block, comptime_arg.ty, uncasted_arg, arg_src); } } @@ -10220,6 +10223,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError .label = &label, .inlining = block.inlining, .is_comptime = block.is_comptime, + .is_typeof = block.is_typeof, .switch_else_err_ty = else_error_ty, .runtime_cond = block.runtime_cond, .runtime_loop = block.runtime_loop, @@ -16411,7 +16415,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE if (!ok) return; // This is only relevant at runtime. - if (block.is_comptime) return; + if (block.is_comptime or block.is_typeof) return; // This is only relevant within functions. if (sema.func == null) return; @@ -16431,7 +16435,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) const src = sema.src; // TODO // This is only relevant at runtime. - if (start_block.is_comptime) return; + if (start_block.is_comptime or start_block.is_typeof) return; const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and @@ -28357,8 +28361,16 @@ fn resolvePeerTypes( const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison(); const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison(); - if (candidate_ty.eql(chosen_ty, sema.mod)) + // If the candidate can coerce into our chosen type, we're done. + // If the chosen type can coerce into the candidate, use that. + if ((try sema.coerceInMemoryAllowed(block, chosen_ty, candidate_ty, false, target, src, src)) == .ok) { + continue; + } + if ((try sema.coerceInMemoryAllowed(block, candidate_ty, chosen_ty, false, target, src, src)) == .ok) { + chosen = candidate; + chosen_i = candidate_i + 1; continue; + } switch (candidate_ty_tag) { .NoReturn, .Undefined => continue, @@ -28758,17 +28770,6 @@ fn resolvePeerTypes( else => {}, } - // If the candidate can coerce into our chosen type, we're done. - // If the chosen type can coerce into the candidate, use that. - if ((try sema.coerceInMemoryAllowed(block, chosen_ty, candidate_ty, false, target, src, src)) == .ok) { - continue; - } - if ((try sema.coerceInMemoryAllowed(block, candidate_ty, chosen_ty, false, target, src, src)) == .ok) { - chosen = candidate; - chosen_i = candidate_i + 1; - continue; - } - // At this point, we hit a compile error. We need to recover // the source locations. const chosen_src = candidate_srcs.resolve( @@ -29092,6 +29093,33 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi struct_obj.backing_int_ty = try backing_int_ty.copy(decl_arena_allocator); try wip_captures.finalize(); } else { + if (fields_bit_sum > std.math.maxInt(u16)) { + var sema: Sema = .{ + .mod = mod, + .gpa = gpa, + .arena = undefined, + .perm_arena = decl_arena_allocator, + .code = zir, + .owner_decl = decl, + .owner_decl_index = decl_index, + .func = null, + .fn_ret_ty = Type.void, + .owner_func = null, + }; + defer sema.deinit(); + + var block: Block = .{ + .parent = null, + .sema = &sema, + .src_decl = decl_index, + .namespace = &struct_obj.namespace, + .wip_capture_scope = undefined, + .instructions = .{}, + .inlining = null, + .is_comptime = true, + }; + return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); + } var buf: Type.Payload.Bits = .{ .base = .{ .tag = .int_unsigned }, .data = @intCast(u16, fields_bit_sum), diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d0f76f0390..6ae11c500d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -730,7 +730,11 @@ pub const DeclGen = struct { } if (ty.optionalReprIsPayload()) { - return dg.renderValue(writer, payload_ty, val, location); + if (val.castTag(.opt_payload)) |payload| { + return dg.renderValue(writer, payload_ty, payload.data, location); + } else { + return dg.renderValue(writer, payload_ty, val, location); + } } try writer.writeByte('('); @@ -3267,11 +3271,9 @@ fn airIsNull( try f.writeCValue(writer, operand); const ty = f.air.typeOf(un_op); + const opt_ty = if (deref_suffix[0] != 0) ty.childType() else ty; var opt_buf: Type.Payload.ElemType = undefined; - const payload_ty = if (deref_suffix[0] != 0) - ty.childType().optionalChild(&opt_buf) - else - ty.optionalChild(&opt_buf); + const payload_ty = opt_ty.optionalChild(&opt_buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { try writer.print("){s} {s} true;\n", .{ deref_suffix, operator }); @@ -3280,6 +3282,8 @@ fn airIsNull( try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator }); } else if (payload_ty.zigTypeTag() == .ErrorSet) { try writer.print("){s} {s} 0;\n", .{ deref_suffix, operator }); + } else if (payload_ty.isSlice() and opt_ty.optionalReprIsPayload()) { + try writer.print("){s}.ptr {s} NULL;\n", .{ deref_suffix, operator }); } else { try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator }); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 1c2d65246f..d92a444ea4 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1027,7 +1027,9 @@ pub const Object = struct { dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); } } - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + if (param_ty.zigTypeTag() != .Optional) { + dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + } if (!ptr_info.mutable) { dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); } @@ -1916,7 +1918,7 @@ pub const Object = struct { if (ty.castTag(.@"struct")) |payload| { const struct_obj = payload.data; - if (struct_obj.layout == .Packed) { + if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { const info = struct_obj.backing_int_ty.intInfo(target); const dwarf_encoding: c_uint = switch (info.signedness) { .signed => DW.ATE.signed, @@ -3117,7 +3119,11 @@ pub const DeclGen = struct { .slice => { const param_ty = fn_info.param_types[it.zig_index - 1]; var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_ty = param_ty.slicePtrFieldType(&buf); + var opt_buf: Type.Payload.ElemType = undefined; + const ptr_ty = if (param_ty.zigTypeTag() == .Optional) + param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf) + else + param_ty.slicePtrFieldType(&buf); const ptr_llvm_ty = try dg.lowerType(ptr_ty); const len_llvm_ty = try dg.lowerType(Type.usize); @@ -5438,10 +5444,11 @@ pub const FuncGen = struct { const llvm_usize = try self.dg.lowerType(Type.usize); const len = llvm_usize.constInt(array_ty.arrayLen(), .False); const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); + const operand = try self.resolveInst(ty_op.operand); if (!array_ty.hasRuntimeBitsIgnoreComptime()) { - return self.builder.buildInsertValue(slice_llvm_ty.getUndef(), len, 1, ""); + const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, ""); + return self.builder.buildInsertValue(partial, len, 1, ""); } - const operand = try self.resolveInst(ty_op.operand); const indices: [2]*llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; @@ -6320,18 +6327,24 @@ pub const FuncGen = struct { const operand_ty = self.air.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; const optional_llvm_ty = try self.dg.lowerType(optional_ty); + var buf: Type.Payload.ElemType = undefined; + const payload_ty = optional_ty.optionalChild(&buf); if (optional_ty.optionalReprIsPayload()) { const loaded = if (operand_is_ptr) self.builder.buildLoad(optional_llvm_ty, operand, "") else operand; + if (payload_ty.isSlice()) { + const slice_ptr = self.builder.buildExtractValue(loaded, 0, ""); + var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; + const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf)); + return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), ""); + } return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); } comptime assert(optional_layout_version == 3); - var buf: Type.Payload.ElemType = undefined; - const payload_ty = optional_ty.optionalChild(&buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { const loaded = if (operand_is_ptr) self.builder.buildLoad(optional_llvm_ty, operand, "") @@ -10355,7 +10368,8 @@ const ParamTypeIterator = struct { .Unspecified, .Inline => { it.zig_index += 1; it.llvm_index += 1; - if (ty.isSlice()) { + var buf: Type.Payload.ElemType = undefined; + if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) { return .slice; } else if (isByRef(ty)) { return .byref; diff --git a/src/translate_c.zig b/src/translate_c.zig index d71e5f30e2..7cc843e17c 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -224,8 +224,7 @@ const Scope = struct { } } - fn findBlockReturnType(inner: *Scope, c: *Context) clang.QualType { - _ = c; + fn findBlockReturnType(inner: *Scope) clang.QualType { var scope = inner; while (true) { switch (scope.id) { @@ -833,7 +832,7 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co if (has_init) trans_init: { if (decl_init) |expr| { const node_or_error = if (expr.getStmtClass() == .StringLiteralClass) - transStringLiteralInitializer(c, scope, @ptrCast(*const clang.StringLiteral, expr), type_node) + transStringLiteralInitializer(c, @ptrCast(*const clang.StringLiteral, expr), type_node) else transExprCoercing(c, scope, expr, .used); init_node = node_or_error catch |err| switch (err) { @@ -1319,10 +1318,10 @@ fn transStmt( .StringLiteralClass => return transStringLiteral(c, scope, @ptrCast(*const clang.StringLiteral, stmt), result_used), .ParenExprClass => { const expr = try transExpr(c, scope, @ptrCast(*const clang.ParenExpr, stmt).getSubExpr(), .used); - return maybeSuppressResult(c, scope, result_used, expr); + return maybeSuppressResult(c, result_used, expr); }, .InitListExprClass => return transInitListExpr(c, scope, @ptrCast(*const clang.InitListExpr, stmt), result_used), - .ImplicitValueInitExprClass => return transImplicitValueInitExpr(c, scope, @ptrCast(*const clang.Expr, stmt), result_used), + .ImplicitValueInitExprClass => return transImplicitValueInitExpr(c, scope, @ptrCast(*const clang.Expr, stmt)), .IfStmtClass => return transIfStmt(c, scope, @ptrCast(*const clang.IfStmt, stmt)), .WhileStmtClass => return transWhileLoop(c, scope, @ptrCast(*const clang.WhileStmt, stmt)), .DoStmtClass => return transDoWhileLoop(c, scope, @ptrCast(*const clang.DoStmt, stmt)), @@ -1332,7 +1331,7 @@ fn transStmt( .ContinueStmtClass => return Tag.@"continue".init(), .BreakStmtClass => return Tag.@"break".init(), .ForStmtClass => return transForLoop(c, scope, @ptrCast(*const clang.ForStmt, stmt)), - .FloatingLiteralClass => return transFloatingLiteral(c, scope, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), + .FloatingLiteralClass => return transFloatingLiteral(c, @ptrCast(*const clang.FloatingLiteral, stmt), result_used), .ConditionalOperatorClass => { return transConditionalOperator(c, scope, @ptrCast(*const clang.ConditionalOperator, stmt), result_used); }, @@ -1356,9 +1355,9 @@ fn transStmt( .OpaqueValueExprClass => { const source_expr = @ptrCast(*const clang.OpaqueValueExpr, stmt).getSourceExpr().?; const expr = try transExpr(c, scope, source_expr, .used); - return maybeSuppressResult(c, scope, result_used, expr); + return maybeSuppressResult(c, result_used, expr); }, - .OffsetOfExprClass => return transOffsetOfExpr(c, scope, @ptrCast(*const clang.OffsetOfExpr, stmt), result_used), + .OffsetOfExprClass => return transOffsetOfExpr(c, @ptrCast(*const clang.OffsetOfExpr, stmt), result_used), .CompoundLiteralExprClass => { const compound_literal = @ptrCast(*const clang.CompoundLiteralExpr, stmt); return transExpr(c, scope, compound_literal.getInitializer(), result_used); @@ -1369,13 +1368,13 @@ fn transStmt( }, .ConvertVectorExprClass => { const conv_vec = @ptrCast(*const clang.ConvertVectorExpr, stmt); - const conv_vec_node = try transConvertVectorExpr(c, scope, stmt.getBeginLoc(), conv_vec); - return maybeSuppressResult(c, scope, result_used, conv_vec_node); + const conv_vec_node = try transConvertVectorExpr(c, scope, conv_vec); + return maybeSuppressResult(c, result_used, conv_vec_node); }, .ShuffleVectorExprClass => { const shuffle_vec_expr = @ptrCast(*const clang.ShuffleVectorExpr, stmt); const shuffle_vec_node = try transShuffleVectorExpr(c, scope, shuffle_vec_expr); - return maybeSuppressResult(c, scope, result_used, shuffle_vec_node); + return maybeSuppressResult(c, result_used, shuffle_vec_node); }, .ChooseExprClass => { const choose_expr = @ptrCast(*const clang.ChooseExpr, stmt); @@ -1402,10 +1401,8 @@ fn transStmt( fn transConvertVectorExpr( c: *Context, scope: *Scope, - source_loc: clang.SourceLocation, expr: *const clang.ConvertVectorExpr, ) TransError!Node { - _ = source_loc; const base_stmt = @ptrCast(*const clang.Stmt, expr); var block_scope = try Scope.Block.init(c, scope, true); @@ -1521,12 +1518,7 @@ fn transShuffleVectorExpr( /// Translate a "simple" offsetof expression containing exactly one component, /// when that component is of kind .Field - e.g. offsetof(mytype, myfield) -fn transSimpleOffsetOfExpr( - c: *Context, - scope: *Scope, - expr: *const clang.OffsetOfExpr, -) TransError!Node { - _ = scope; +fn transSimpleOffsetOfExpr(c: *Context, expr: *const clang.OffsetOfExpr) TransError!Node { assert(expr.getNumComponents() == 1); const component = expr.getComponent(0); if (component.getKind() == .Field) { @@ -1551,13 +1543,12 @@ fn transSimpleOffsetOfExpr( fn transOffsetOfExpr( c: *Context, - scope: *Scope, expr: *const clang.OffsetOfExpr, result_used: ResultUsed, ) TransError!Node { if (expr.getNumComponents() == 1) { - const offsetof_expr = try transSimpleOffsetOfExpr(c, scope, expr); - return maybeSuppressResult(c, scope, result_used, offsetof_expr); + const offsetof_expr = try transSimpleOffsetOfExpr(c, expr); + return maybeSuppressResult(c, result_used, offsetof_expr); } // TODO implement OffsetOfExpr with more than 1 component @@ -1613,7 +1604,6 @@ fn transCreatePointerArithmeticSignedOp( return transCreateNodeInfixOp( c, - scope, if (is_add) .add else .sub, lhs_node, bitcast_node, @@ -1629,7 +1619,7 @@ fn transBinaryOperator( ) TransError!Node { const op = stmt.getOpcode(); const qt = stmt.getType(); - const isPointerDiffExpr = cIsPointerDiffExpr(c, stmt); + const isPointerDiffExpr = cIsPointerDiffExpr(stmt); switch (op) { .Assign => return try transCreateNodeAssign(c, scope, result_used, stmt.getLHS(), stmt.getRHS()), .Comma => { @@ -1646,7 +1636,7 @@ fn transBinaryOperator( }); try block_scope.statements.append(break_node); const block_node = try block_scope.complete(c); - return maybeSuppressResult(c, scope, result_used, block_node); + return maybeSuppressResult(c, result_used, block_node); }, .Div => { if (cIsSignedInteger(qt)) { @@ -1654,7 +1644,7 @@ fn transBinaryOperator( const lhs = try transExpr(c, scope, stmt.getLHS(), .used); const rhs = try transExpr(c, scope, stmt.getRHS(), .used); const div_trunc = try Tag.div_trunc.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); - return maybeSuppressResult(c, scope, result_used, div_trunc); + return maybeSuppressResult(c, result_used, div_trunc); } }, .Rem => { @@ -1663,7 +1653,7 @@ fn transBinaryOperator( const lhs = try transExpr(c, scope, stmt.getLHS(), .used); const rhs = try transExpr(c, scope, stmt.getRHS(), .used); const rem = try Tag.signed_remainder.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); - return maybeSuppressResult(c, scope, result_used, rem); + return maybeSuppressResult(c, result_used, rem); } }, .Shl => { @@ -1764,7 +1754,7 @@ fn transBinaryOperator( else rhs_uncasted; - const infixOpNode = try transCreateNodeInfixOp(c, scope, op_id, lhs, rhs, result_used); + const infixOpNode = try transCreateNodeInfixOp(c, op_id, lhs, rhs, result_used); if (isPointerDiffExpr) { // @divExact(@bitCast(<platform-ptrdiff_t>, @ptrToInt(lhs) -% @ptrToInt(rhs)), @sizeOf(<lhs target type>)) const ptrdiff_type = try transQualTypeIntWidthOf(c, qt, true); @@ -1843,7 +1833,7 @@ fn transCStyleCastExprClass( src_type, sub_expr_node, )); - return maybeSuppressResult(c, scope, result_used, cast_node); + return maybeSuppressResult(c, result_used, cast_node); } /// The alignment of a variable or field @@ -1933,7 +1923,7 @@ fn transDeclStmtOne( var init_node = if (decl_init) |expr| if (expr.getStmtClass() == .StringLiteralClass) - try transStringLiteralInitializer(c, scope, @ptrCast(*const clang.StringLiteral, expr), type_node) + try transStringLiteralInitializer(c, @ptrCast(*const clang.StringLiteral, expr), type_node) else try transExprCoercing(c, scope, expr, .used) else if (is_static_local) @@ -2051,21 +2041,21 @@ fn transImplicitCastExpr( .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast, .PointerToIntegral, .IntegralToPointer => { const sub_expr_node = try transExpr(c, scope, sub_expr, .used); const casted = try transCCast(c, scope, expr.getBeginLoc(), dest_type, src_type, sub_expr_node); - return maybeSuppressResult(c, scope, result_used, casted); + return maybeSuppressResult(c, result_used, casted); }, .LValueToRValue, .NoOp, .FunctionToPointerDecay => { const sub_expr_node = try transExpr(c, scope, sub_expr, .used); - return maybeSuppressResult(c, scope, result_used, sub_expr_node); + return maybeSuppressResult(c, result_used, sub_expr_node); }, .ArrayToPointerDecay => { const sub_expr_node = try transExpr(c, scope, sub_expr, .used); if (exprIsNarrowStringLiteral(sub_expr) or exprIsFlexibleArrayRef(c, sub_expr)) { - return maybeSuppressResult(c, scope, result_used, sub_expr_node); + return maybeSuppressResult(c, result_used, sub_expr_node); } const addr = try Tag.address_of.create(c.arena, sub_expr_node); const casted = try transCPtrCast(c, scope, expr.getBeginLoc(), dest_type, src_type, addr); - return maybeSuppressResult(c, scope, result_used, casted); + return maybeSuppressResult(c, result_used, casted); }, .NullToPointer => { return Tag.null_literal.init(); @@ -2076,18 +2066,18 @@ fn transImplicitCastExpr( const ptr_to_int = try Tag.ptr_to_int.create(c.arena, ptr_node); const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() }); - return maybeSuppressResult(c, scope, result_used, ne); + return maybeSuppressResult(c, result_used, ne); }, .IntegralToBoolean, .FloatingToBoolean => { const sub_expr_node = try transExpr(c, scope, sub_expr, .used); // The expression is already a boolean one, return it as-is if (isBoolRes(sub_expr_node)) - return maybeSuppressResult(c, scope, result_used, sub_expr_node); + return maybeSuppressResult(c, result_used, sub_expr_node); // val != 0 const ne = try Tag.not_equal.create(c.arena, .{ .lhs = sub_expr_node, .rhs = Tag.zero_literal.init() }); - return maybeSuppressResult(c, scope, result_used, ne); + return maybeSuppressResult(c, result_used, ne); }, .BuiltinFnToFnPtr => { return transBuiltinFnExpr(c, scope, sub_expr, result_used); @@ -2140,13 +2130,13 @@ fn transBoolExpr( var res = try transExpr(c, scope, expr, used); if (isBoolRes(res)) { - return maybeSuppressResult(c, scope, used, res); + return maybeSuppressResult(c, used, res); } const ty = getExprQualType(c, expr).getTypePtr(); const node = try finishBoolExpr(c, scope, expr.getBeginLoc(), ty, res, used); - return maybeSuppressResult(c, scope, used, node); + return maybeSuppressResult(c, used, node); } fn exprIsBooleanType(expr: *const clang.Expr) bool { @@ -2299,7 +2289,7 @@ fn transIntegerLiteral( if (suppress_as == .no_as) { const int_lit_node = try transCreateNodeAPInt(c, eval_result.Val.getInt()); - return maybeSuppressResult(c, scope, result_used, int_lit_node); + return maybeSuppressResult(c, result_used, int_lit_node); } // Integer literals in C have types, and this can matter for several reasons. @@ -2317,7 +2307,7 @@ fn transIntegerLiteral( const ty_node = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()); const rhs = try transCreateNodeAPInt(c, eval_result.Val.getInt()); const as = try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = rhs }); - return maybeSuppressResult(c, scope, result_used, as); + return maybeSuppressResult(c, result_used, as); } fn transReturnStmt( @@ -2329,7 +2319,7 @@ fn transReturnStmt( return Tag.return_void.init(); var rhs = try transExprCoercing(c, scope, val_expr, .used); - const return_qt = scope.findBlockReturnType(c); + const return_qt = scope.findBlockReturnType(); if (isBoolRes(rhs) and !qualTypeIsBoolean(return_qt)) { rhs = try Tag.bool_to_int.create(c.arena, rhs); } @@ -2338,7 +2328,6 @@ fn transReturnStmt( fn transNarrowStringLiteral( c: *Context, - scope: *Scope, stmt: *const clang.StringLiteral, result_used: ResultUsed, ) TransError!Node { @@ -2347,7 +2336,7 @@ fn transNarrowStringLiteral( const str = try std.fmt.allocPrint(c.arena, "\"{}\"", .{std.zig.fmtEscapes(bytes_ptr[0..len])}); const node = try Tag.string_literal.create(c.arena, str); - return maybeSuppressResult(c, scope, result_used, node); + return maybeSuppressResult(c, result_used, node); } fn transStringLiteral( @@ -2358,18 +2347,18 @@ fn transStringLiteral( ) TransError!Node { const kind = stmt.getKind(); switch (kind) { - .Ascii, .UTF8 => return transNarrowStringLiteral(c, scope, stmt, result_used), + .Ascii, .UTF8 => return transNarrowStringLiteral(c, stmt, result_used), .UTF16, .UTF32, .Wide => { const str_type = @tagName(stmt.getKind()); const name = try std.fmt.allocPrint(c.arena, "zig.{s}_string_{d}", .{ str_type, c.getMangle() }); const expr_base = @ptrCast(*const clang.Expr, stmt); const array_type = try transQualTypeInitialized(c, scope, expr_base.getType(), expr_base, expr_base.getBeginLoc()); - const lit_array = try transStringLiteralInitializer(c, scope, stmt, array_type); + const lit_array = try transStringLiteralInitializer(c, stmt, array_type); const decl = try Tag.var_simple.create(c.arena, .{ .name = name, .init = lit_array }); try scope.appendNode(decl); const node = try Tag.identifier.create(c.arena, name); - return maybeSuppressResult(c, scope, result_used, node); + return maybeSuppressResult(c, result_used, node); }, } } @@ -2384,7 +2373,6 @@ fn getArrayPayload(array_type: Node) ast.Payload.Array.ArrayTypeInfo { /// the appropriate length, if necessary. fn transStringLiteralInitializer( c: *Context, - scope: *Scope, stmt: *const clang.StringLiteral, array_type: Node, ) TransError!Node { @@ -2403,7 +2391,7 @@ fn transStringLiteralInitializer( const init_node = if (num_inits > 0) blk: { if (is_narrow) { // "string literal".* or string literal"[0..num_inits].* - var str = try transNarrowStringLiteral(c, scope, stmt, .used); + var str = try transNarrowStringLiteral(c, stmt, .used); if (str_length != array_size) str = try Tag.string_slice.create(c.arena, .{ .string = str, .end = num_inits }); break :blk try Tag.deref.create(c.arena, str); } else { @@ -2440,8 +2428,7 @@ fn transStringLiteralInitializer( /// determine whether `stmt` is a "pointer subtraction expression" - a subtraction where /// both operands resolve to addresses. The C standard requires that both operands /// point to elements of the same array object, but we do not verify that here. -fn cIsPointerDiffExpr(c: *Context, stmt: *const clang.BinaryOperator) bool { - _ = c; +fn cIsPointerDiffExpr(stmt: *const clang.BinaryOperator) bool { const lhs = @ptrCast(*const clang.Stmt, stmt.getLHS()); const rhs = @ptrCast(*const clang.Stmt, stmt.getRHS()); return stmt.getOpcode() == .Sub and @@ -2748,9 +2735,7 @@ fn transInitListExprVector( scope: *Scope, loc: clang.SourceLocation, expr: *const clang.InitListExpr, - ty: *const clang.Type, ) TransError!Node { - _ = ty; const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr)); const vector_ty = @ptrCast(*const clang.VectorType, qualTypeCanon(qt)); @@ -2829,7 +2814,7 @@ fn transInitListExpr( } if (qual_type.isRecordType()) { - return maybeSuppressResult(c, scope, used, try transInitListExprRecord( + return maybeSuppressResult(c, used, try transInitListExprRecord( c, scope, source_loc, @@ -2837,7 +2822,7 @@ fn transInitListExpr( qual_type, )); } else if (qual_type.isArrayType()) { - return maybeSuppressResult(c, scope, used, try transInitListExprArray( + return maybeSuppressResult(c, used, try transInitListExprArray( c, scope, source_loc, @@ -2845,13 +2830,7 @@ fn transInitListExpr( qual_type, )); } else if (qual_type.isVectorType()) { - return maybeSuppressResult(c, scope, used, try transInitListExprVector( - c, - scope, - source_loc, - expr, - qual_type, - )); + return maybeSuppressResult(c, used, try transInitListExprVector(c, scope, source_loc, expr)); } else { const type_name = try c.str(qual_type.getTypeClassName()); return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name}); @@ -2912,9 +2891,7 @@ fn transImplicitValueInitExpr( c: *Context, scope: *Scope, expr: *const clang.Expr, - used: ResultUsed, ) TransError!Node { - _ = used; const source_loc = expr.getBeginLoc(); const qt = getExprQualType(c, expr); const ty = qt.getTypePtr(); @@ -3354,7 +3331,7 @@ fn transConstantExpr(c: *Context, scope: *Scope, expr: *const clang.Expr, used: .lhs = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()), .rhs = try transCreateNodeAPInt(c, result.Val.getInt()), }); - return maybeSuppressResult(c, scope, used, as_node); + return maybeSuppressResult(c, used, as_node); }, else => |kind| { return fail(c, error.UnsupportedTranslation, expr.getBeginLoc(), "unsupported constant expression kind '{}'", .{kind}); @@ -3391,7 +3368,7 @@ fn transCharLiteral( try transCreateCharLitNode(c, narrow, val); if (suppress_as == .no_as) { - return maybeSuppressResult(c, scope, result_used, int_lit_node); + return maybeSuppressResult(c, result_used, int_lit_node); } // See comment in `transIntegerLiteral` for why this code is here. // @as(T, x) @@ -3400,7 +3377,7 @@ fn transCharLiteral( .lhs = try transQualType(c, scope, expr_base.getType(), expr_base.getBeginLoc()), .rhs = int_lit_node, }); - return maybeSuppressResult(c, scope, result_used, as_node); + return maybeSuppressResult(c, result_used, as_node); } fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: ResultUsed) TransError!Node { @@ -3426,7 +3403,7 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used: }); try block_scope.statements.append(break_node); const res = try block_scope.complete(c); - return maybeSuppressResult(c, scope, used, res); + return maybeSuppressResult(c, used, res); } fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, result_used: ResultUsed) TransError!Node { @@ -3455,7 +3432,7 @@ fn transMemberExpr(c: *Context, scope: *Scope, stmt: *const clang.MemberExpr, re if (exprIsFlexibleArrayRef(c, @ptrCast(*const clang.Expr, stmt))) { node = try Tag.call.create(c.arena, .{ .lhs = node, .args = &.{} }); } - return maybeSuppressResult(c, scope, result_used, node); + return maybeSuppressResult(c, result_used, node); } /// ptr[subscr] (`subscr` is a signed integer expression, `ptr` a pointer) becomes: @@ -3533,7 +3510,7 @@ fn transSignedArrayAccess( const derefed = try Tag.deref.create(c.arena, block_node); - return maybeSuppressResult(c, &block_scope.base, result_used, derefed); + return maybeSuppressResult(c, result_used, derefed); } fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscriptExpr, result_used: ResultUsed) TransError!Node { @@ -3574,7 +3551,7 @@ fn transArrayAccess(c: *Context, scope: *Scope, stmt: *const clang.ArraySubscrip .lhs = container_node, .rhs = rhs, }); - return maybeSuppressResult(c, scope, result_used, node); + return maybeSuppressResult(c, result_used, node); } /// Check if an expression is ultimately a reference to a function declaration @@ -3665,7 +3642,7 @@ fn transCallExpr(c: *Context, scope: *Scope, stmt: *const clang.CallExpr, result } } - return maybeSuppressResult(c, scope, result_used, node); + return maybeSuppressResult(c, result_used, node); } const ClangFunctionType = union(enum) { @@ -3705,14 +3682,13 @@ fn transUnaryExprOrTypeTraitExpr( stmt: *const clang.UnaryExprOrTypeTraitExpr, result_used: ResultUsed, ) TransError!Node { - _ = result_used; const loc = stmt.getBeginLoc(); const type_node = try transQualType(c, scope, stmt.getTypeOfArgument(), loc); const kind = stmt.getKind(); - switch (kind) { - .SizeOf => return Tag.sizeof.create(c.arena, type_node), - .AlignOf => return Tag.alignof.create(c.arena, type_node), + const node = switch (kind) { + .SizeOf => try Tag.sizeof.create(c.arena, type_node), + .AlignOf => try Tag.alignof.create(c.arena, type_node), .PreferredAlignOf, .VecStep, .OpenMPRequiredSimdAlign, @@ -3723,7 +3699,8 @@ fn transUnaryExprOrTypeTraitExpr( "unsupported type trait kind {}", .{kind}, ), - } + }; + return maybeSuppressResult(c, result_used, node); } fn qualTypeHasWrappingOverflow(qt: clang.QualType) bool { @@ -3812,7 +3789,7 @@ fn transCreatePreCrement( // zig: expr += 1 const lhs = try transExpr(c, scope, op_expr, .used); const rhs = Tag.one_literal.init(); - return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used); + return transCreateNodeInfixOp(c, op, lhs, rhs, .used); } // worst case // c: ++expr @@ -3832,7 +3809,7 @@ fn transCreatePreCrement( const lhs_node = try Tag.identifier.create(c.arena, ref); const ref_node = try Tag.deref.create(c.arena, lhs_node); - const node = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, Tag.one_literal.init(), .used); + const node = try transCreateNodeInfixOp(c, op, ref_node, Tag.one_literal.init(), .used); try block_scope.statements.append(node); const break_node = try Tag.break_val.create(c.arena, .{ @@ -3858,7 +3835,7 @@ fn transCreatePostCrement( // zig: expr += 1 const lhs = try transExpr(c, scope, op_expr, .used); const rhs = Tag.one_literal.init(); - return transCreateNodeInfixOp(c, scope, op, lhs, rhs, .used); + return transCreateNodeInfixOp(c, op, lhs, rhs, .used); } // worst case // c: expr++ @@ -3884,7 +3861,7 @@ fn transCreatePostCrement( const tmp_decl = try Tag.var_simple.create(c.arena, .{ .name = tmp, .init = ref_node }); try block_scope.statements.append(tmp_decl); - const node = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, Tag.one_literal.init(), .used); + const node = try transCreateNodeInfixOp(c, op, ref_node, Tag.one_literal.init(), .used); try block_scope.statements.append(node); const break_node = try Tag.break_val.create(c.arena, .{ @@ -3965,7 +3942,7 @@ fn transCreateCompoundAssign( else try Tag.div_trunc.create(c.arena, operands); - return transCreateNodeInfixOp(c, scope, .assign, lhs_node, builtin, .used); + return transCreateNodeInfixOp(c, .assign, lhs_node, builtin, .used); } if (is_shift) { @@ -3974,7 +3951,7 @@ fn transCreateCompoundAssign( } else if (requires_int_cast) { rhs_node = try transCCast(c, scope, loc, lhs_qt, rhs_qt, rhs_node); } - return transCreateNodeInfixOp(c, scope, op, lhs_node, rhs_node, .used); + return transCreateNodeInfixOp(c, op, lhs_node, rhs_node, .used); } // worst case // c: lhs += rhs @@ -4005,7 +3982,7 @@ fn transCreateCompoundAssign( else try Tag.div_trunc.create(c.arena, operands); - const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, ref_node, builtin, .used); + const assign = try transCreateNodeInfixOp(c, .assign, ref_node, builtin, .used); try block_scope.statements.append(assign); } else { if (is_shift) { @@ -4015,7 +3992,7 @@ fn transCreateCompoundAssign( rhs_node = try transCCast(c, &block_scope.base, loc, lhs_qt, rhs_qt, rhs_node); } - const assign = try transCreateNodeInfixOp(c, &block_scope.base, op, ref_node, rhs_node, .used); + const assign = try transCreateNodeInfixOp(c, op, ref_node, rhs_node, .used); try block_scope.statements.append(assign); } @@ -4071,7 +4048,7 @@ fn transCPtrCast( } } -fn transFloatingLiteral(c: *Context, scope: *Scope, expr: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node { +fn transFloatingLiteral(c: *Context, expr: *const clang.FloatingLiteral, used: ResultUsed) TransError!Node { switch (expr.getRawSemantics()) { .IEEEhalf, // f16 .IEEEsingle, // f32 @@ -4095,7 +4072,7 @@ fn transFloatingLiteral(c: *Context, scope: *Scope, expr: *const clang.FloatingL try std.fmt.allocPrint(c.arena, "{d}", .{dbl}); var node = try Tag.float_literal.create(c.arena, str); if (is_negative) node = try Tag.negate.create(c.arena, node); - return maybeSuppressResult(c, scope, used, node); + return maybeSuppressResult(c, used, node); } fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.BinaryConditionalOperator, used: ResultUsed) TransError!Node { @@ -4151,7 +4128,7 @@ fn transBinaryConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang }); try block_scope.statements.append(break_node); const res = try block_scope.complete(c); - return maybeSuppressResult(c, scope, used, res); + return maybeSuppressResult(c, used, res); } fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.ConditionalOperator, used: ResultUsed) TransError!Node { @@ -4191,13 +4168,7 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi return if_node; } -fn maybeSuppressResult( - c: *Context, - scope: *Scope, - used: ResultUsed, - result: Node, -) TransError!Node { - _ = scope; +fn maybeSuppressResult(c: *Context, used: ResultUsed, result: Node) TransError!Node { if (used == .used) return result; return Tag.discard.create(c.arena, .{ .should_skip = false, .value = result }); } @@ -4551,7 +4522,7 @@ fn transCreateNodeAssign( if (!exprIsBooleanType(lhs) and isBoolRes(rhs_node)) { rhs_node = try Tag.bool_to_int.create(c.arena, rhs_node); } - return transCreateNodeInfixOp(c, scope, .assign, lhs_node, rhs_node, .used); + return transCreateNodeInfixOp(c, .assign, lhs_node, rhs_node, .used); } // worst case @@ -4571,7 +4542,7 @@ fn transCreateNodeAssign( const lhs_node = try transExpr(c, &block_scope.base, lhs, .used); const tmp_ident = try Tag.identifier.create(c.arena, tmp); - const assign = try transCreateNodeInfixOp(c, &block_scope.base, .assign, lhs_node, tmp_ident, .used); + const assign = try transCreateNodeInfixOp(c, .assign, lhs_node, tmp_ident, .used); try block_scope.statements.append(assign); const break_node = try Tag.break_val.create(c.arena, .{ @@ -4584,7 +4555,6 @@ fn transCreateNodeAssign( fn transCreateNodeInfixOp( c: *Context, - scope: *Scope, op: Tag, lhs: Node, rhs: Node, @@ -4598,7 +4568,7 @@ fn transCreateNodeInfixOp( .rhs = rhs, }, }; - return maybeSuppressResult(c, scope, used, Node.initPayload(&payload.base)); + return maybeSuppressResult(c, used, Node.initPayload(&payload.base)); } fn transCreateNodeBoolInfixOp( @@ -4613,7 +4583,7 @@ fn transCreateNodeBoolInfixOp( const lhs = try transBoolExpr(c, scope, stmt.getLHS(), .used); const rhs = try transBoolExpr(c, scope, stmt.getRHS(), .used); - return transCreateNodeInfixOp(c, scope, op, lhs, rhs, used); + return transCreateNodeInfixOp(c, op, lhs, rhs, used); } fn transCreateNodeAPInt(c: *Context, int: *const clang.APSInt) !Node { @@ -4730,7 +4700,7 @@ fn transCreateNodeShiftOp( const rhs = try transExprCoercing(c, scope, rhs_expr, .used); const rhs_casted = try Tag.int_cast.create(c.arena, .{ .lhs = rhs_type, .rhs = rhs }); - return transCreateNodeInfixOp(c, scope, op, lhs, rhs_casted, used); + return transCreateNodeInfixOp(c, op, lhs, rhs_casted, used); } fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clang.SourceLocation) TypeError!Node { @@ -5681,13 +5651,14 @@ const ParseError = Error || error{ParseError}; fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { // TODO parseCAssignExpr here - const node = try parseCCondExpr(c, m, scope); + var block_scope = try Scope.Block.init(c, scope, true); + defer block_scope.deinit(); + + const node = try parseCCondExpr(c, m, &block_scope.base); if (m.next().? != .Comma) { m.i -= 1; return node; } - var block_scope = try Scope.Block.init(c, scope, true); - defer block_scope.deinit(); var last = node; while (true) { @@ -6298,7 +6269,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { // allow_fail is set when unsure if we are parsing a type-name fn parseCTypeName(c: *Context, m: *MacroCtx, scope: *Scope, allow_fail: bool) ParseError!?Node { if (try parseCSpecifierQualifierList(c, m, scope, allow_fail)) |node| { - return try parseCAbstractDeclarator(c, m, scope, node); + return try parseCAbstractDeclarator(c, m, node); } else { return null; } @@ -6327,7 +6298,7 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ .Keyword_complex, => { m.i -= 1; - return try parseCNumericType(c, m, scope); + return try parseCNumericType(c, m); }, .Keyword_enum, .Keyword_struct, .Keyword_union => { // struct Foo will be declared as struct_Foo by transRecordDecl @@ -6349,8 +6320,7 @@ fn parseCSpecifierQualifierList(c: *Context, m: *MacroCtx, scope: *Scope, allow_ } } -fn parseCNumericType(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { - _ = scope; +fn parseCNumericType(c: *Context, m: *MacroCtx) ParseError!Node { const KwCounter = struct { double: u8 = 0, long: u8 = 0, @@ -6451,8 +6421,7 @@ fn parseCNumericType(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { return error.ParseError; } -fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, scope: *Scope, node: Node) ParseError!Node { - _ = scope; +fn parseCAbstractDeclarator(c: *Context, m: *MacroCtx, node: Node) ParseError!Node { switch (m.next().?) { .Asterisk => { // last token of `node` diff --git a/src/type.zig b/src/type.zig index 8f2cd7c54d..b4015427c8 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3434,20 +3434,8 @@ pub const Type = extern union { if (!child_type.hasRuntimeBits()) return AbiSizeAdvanced{ .scalar = 1 }; - switch (child_type.zigTypeTag()) { - .Pointer => { - const ptr_info = child_type.ptrInfo().data; - const has_null = switch (ptr_info.size) { - .Slice, .C => true, - else => ptr_info.@"allowzero", - }; - if (!has_null) { - const ptr_size_bytes = @divExact(target.cpu.arch.ptrBitWidth(), 8); - return AbiSizeAdvanced{ .scalar = ptr_size_bytes }; - } - }, - .ErrorSet => return abiSizeAdvanced(Type.anyerror, target, strat), - else => {}, + if (ty.optionalReprIsPayload()) { + return abiSizeAdvanced(child_type, target, strat); } const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) { @@ -3712,28 +3700,10 @@ pub const Type = extern union { .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data, - .optional => { - var buf: Payload.ElemType = undefined; - const child_type = ty.optionalChild(&buf); - if (!child_type.hasRuntimeBits()) return 8; - - if (child_type.zigTypeTag() == .Pointer and !child_type.isCPtr() and !child_type.isSlice()) - return target.cpu.arch.ptrBitWidth(); - - // Optional types are represented as a struct with the child type as the first - // field and a boolean as the second. Since the child type's abi alignment is - // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal - // to the child type's ABI alignment. - const child_bit_size = try bitSizeAdvanced(child_type, target, sema_kit); - return child_bit_size + 1; - }, - - .error_union => { - const payload = ty.castTag(.error_union).?.data; - if (!payload.payload.hasRuntimeBits()) { - return payload.error_set.bitSizeAdvanced(target, sema_kit); - } - @panic("TODO bitSize error union"); + .optional, .error_union => { + // Optionals and error unions are not packed so their bitsize + // includes padding bits. + return (try abiSizeAdvanced(ty, target, if (sema_kit) |sk| .{ .sema_kit = sk } else .eager)).scalar * 8; }, .atomic_order, @@ -4010,8 +3980,8 @@ pub const Type = extern union { .Pointer => { const info = child_ty.ptrInfo().data; switch (info.size) { - .Slice, .C => return false, - .Many, .One => return !info.@"allowzero", + .C => return false, + .Slice, .Many, .One => return !info.@"allowzero", } }, .ErrorSet => return true, |
