kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit ed9a6cddccc301aecb643dfdfd2f96a782dd63d9
parent 8626ea4a1c51ff379de454ddd107dea711309609
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 19 May 2026 18:22:47 -0700

Fix C pointer constant cases

Diffstat:
Mlang/c/parse/cg_adapter.c | 47+++++++++++++++++++++++++++++------------------
Mlang/c/parse/parse_expr.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mlang/c/parse/parse_init.c | 64++++++++++++++++++++++++++++++++++++++++++----------------------
Mlang/c/type/type.c | 9+++++++++
Atest/parse/cases/6_4_4_1_hex_ll_unsigned_fallback.c | 5+++++
Atest/parse/cases/6_4_4_1_hex_ll_unsigned_fallback.expected | 1+
Atest/parse/cases/6_5_3_2_04_call_deref_function_pointer.c | 11+++++++++++
Atest/parse/cases/6_5_3_2_04_call_deref_function_pointer.expected | 1+
Atest/parse/cases/6_6_12_cast_addr_const_static_init.c | 6++++++
Atest/parse/cases/6_6_12_cast_addr_const_static_init.expected | 1+
Atest/parse/cases/6_7_2_3_03_qualified_forward_member.c | 10++++++++++
Atest/parse/cases/6_7_2_3_03_qualified_forward_member.expected | 1+
Atest/parse/cases/6_7_9_32_static_ptr_cast_nonzero_int.c | 2++
Atest/parse/cases/6_7_9_32_static_ptr_cast_nonzero_int.expected | 1+
Atest/parse/cases/6_7_9_33_static_struct_ptr_cast_nonzero_int.c | 9+++++++++
Atest/parse/cases/6_7_9_33_static_struct_ptr_cast_nonzero_int.expected | 1+
16 files changed, 256 insertions(+), 117 deletions(-)

diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c @@ -126,7 +126,8 @@ int pcg_top_is_bitfield(Parser* p) { } void pcg_set_top_bitfield(Parser* p) { - if (p->cg_type_sp) p->cg_value_flags[p->cg_type_sp - 1u] |= PCG_VALUE_BITFIELD; + if (p->cg_type_sp) + p->cg_value_flags[p->cg_type_sp - 1u] |= PCG_VALUE_BITFIELD; } int pcg_top_is_register(Parser* p) { @@ -145,22 +146,20 @@ int pcg_top_is_lvalue(Parser* p) { } int pcg_top_is_modifiable_lvalue(Parser* p) { - return p->cg_type_sp && - (p->cg_value_flags[p->cg_type_sp - 1u] & - (PCG_VALUE_LVALUE | PCG_VALUE_MODIFIABLE)) == - (PCG_VALUE_LVALUE | PCG_VALUE_MODIFIABLE); + return p->cg_type_sp && (p->cg_value_flags[p->cg_type_sp - 1u] & + (PCG_VALUE_LVALUE | PCG_VALUE_MODIFIABLE)) == + (PCG_VALUE_LVALUE | PCG_VALUE_MODIFIABLE); } int pcg_top_is_null_ptr_const(Parser* p) { - return p->cg_type_sp && - (p->cg_value_flags[p->cg_type_sp - 1u] & - PCG_VALUE_NULL_PTR_CONST) != 0; + return p->cg_type_sp && (p->cg_value_flags[p->cg_type_sp - 1u] & + PCG_VALUE_NULL_PTR_CONST) != 0; } void pcg_set_top_lvalue(Parser* p) { const Type* ty = pcg_top_type(p); - if (p->cg_type_sp) p->cg_value_flags[p->cg_type_sp - 1u] = - pcg_lvalue_flags_for_type(ty); + if (p->cg_type_sp) + p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(ty); } int pcg_emit_enabled(Parser* p) { return p && p->suppress_codegen == 0; } @@ -171,7 +170,8 @@ void pcg_codegen_suppress_push(Parser* p) { void pcg_codegen_suppress_pop(Parser* p) { if (!p) return; - if (!p->suppress_codegen) perr(p, "internal parser codegen suppression underflow"); + if (!p->suppress_codegen) + perr(p, "internal parser codegen suppression underflow"); --p->suppress_codegen; } @@ -359,15 +359,15 @@ void pcg_push_float(Parser* p, double v, const Type* ty) { void pcg_push_local_typed(Parser* p, FrameSlot s, const Type* ty) { if (pcg_emit_enabled(p)) cfree_cg_push_local(p->cg, s); pcg_push_type(p, ty); - if (p->cg_type_sp) p->cg_value_flags[p->cg_type_sp - 1u] = - pcg_lvalue_flags_for_type(ty); + if (p->cg_type_sp) + p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(ty); } void pcg_push_global(Parser* p, ObjSymId sym, const Type* ty) { if (pcg_emit_enabled(p)) cfree_cg_push_symbol_lvalue(p->cg, sym, 0); pcg_push_type(p, ty); - if (p->cg_type_sp) p->cg_value_flags[p->cg_type_sp - 1u] = - pcg_lvalue_flags_for_type(ty); + if (p->cg_type_sp) + p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(ty); } void pcg_load(Parser* p) { @@ -401,10 +401,20 @@ void pcg_store(Parser* p) { } void pcg_deref(Parser* p, const Type* pointee) { + const Type* ptr_ty = pcg_top_type(p); + if (pointee && pointee->kind == TY_FUNC) { + pcg_retag_top(p, pointee); + return; + } + if (ptr_ty && ptr_ty->kind == TY_PTR && ptr_ty->ptr.pointee != pointee) { + const Type* want_ptr_ty = type_ptr(p->pool, pointee); + if (pcg_emit_enabled(p)) cfree_cg_bitcast(p->cg, pcg_tid(p, want_ptr_ty)); + pcg_retag_top(p, want_ptr_ty); + } if (pcg_emit_enabled(p)) cfree_cg_indirect(p->cg); pcg_retag_top(p, pointee); - if (p->cg_type_sp) p->cg_value_flags[p->cg_type_sp - 1u] = - pcg_lvalue_flags_for_type(pointee); + if (p->cg_type_sp) + p->cg_value_flags[p->cg_type_sp - 1u] = pcg_lvalue_flags_for_type(pointee); } void pcg_binop(Parser* p, BinOp op) { @@ -424,7 +434,8 @@ void pcg_binop(Parser* p, BinOp op) { void pcg_unop(Parser* p, UnOp op) { if (op == UO_NEG && pcg_type_is_fp(pcg_top_type(p))) { - if (pcg_emit_enabled(p)) cfree_cg_fp_unop(p->cg, CFREE_CG_FP_NEG, CFREE_CG_FP_NONE); + if (pcg_emit_enabled(p)) + cfree_cg_fp_unop(p->cg, CFREE_CG_FP_NEG, CFREE_CG_FP_NONE); } else { CfreeCgIntUnOp iop = op == UO_NOT ? CFREE_CG_INT_NOT : op == UO_BNOT ? CFREE_CG_INT_BNOT diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c @@ -1,8 +1,8 @@ /* parse_expr.c — precedence climbing, unary/primary, literal decoding, * constant evaluation. */ -#include "parse/parse_priv.h" #include "parse/literal_unicode.h" +#include "parse/parse_priv.h" static const Type* ty_int(Parser* p) { return type_prim(p->pool, TY_INT); } static const Type* ty_size_t(Parser* p) { @@ -61,9 +61,8 @@ static int pointer_pointees_compatible(Parser* p, const Type* lhs, static int null_pointer_constant(Parser* p, const Type* ty) { i64 v = 1; - return type_is_int(ty) && - (pcg_top_is_null_ptr_const(p) || - (cfree_cg_top_const_int(p->cg, &v) && v == 0)); + return type_is_int(ty) && (pcg_top_is_null_ptr_const(p) || + (cfree_cg_top_const_int(p->cg, &v) && v == 0)); } static void require_scalar(Parser* p, const Type* ty, const char* what) { @@ -75,12 +74,12 @@ static void require_arith(Parser* p, const Type* ty, const char* what) { } static const Type* conditional_pointer_type(Parser* p, const Type* then_ty, - int then_null, - const Type* else_ty, + int then_null, const Type* else_ty, int else_null) { if (then_ty && then_ty->kind == TY_PTR && else_null) return then_ty; if (else_ty && else_ty->kind == TY_PTR && then_null) return else_ty; - if (!then_ty || !else_ty || then_ty->kind != TY_PTR || else_ty->kind != TY_PTR) + if (!then_ty || !else_ty || then_ty->kind != TY_PTR || + else_ty->kind != TY_PTR) return NULL; if (type_is_void_ptr(then_ty)) return then_ty; if (type_is_void_ptr(else_ty)) return else_ty; @@ -129,8 +128,7 @@ static u64 parse_int_literal_u64(Parser* p, const Tok* t, int* decimal_out) { else perr(p, "bad digit in numeric literal"); if ((u64)dv >= base) perr(p, "digit out of range for base"); - if (acc > (~0ull - (u64)dv) / base) - perr(p, "integer literal too large"); + if (acc > (~0ull - (u64)dv) / base) perr(p, "integer literal too large"); acc = acc * base + dv; } if (decimal_out) *decimal_out = decimal; @@ -169,38 +167,49 @@ static const Type* int_literal_type(Parser* p, const Tok* t) { u64 v = parse_int_literal_u64(p, t, &decimal); if (u && ll) { static const TypeKind order[] = {TY_ULLONG}; - return first_fitting_type(p, v, order, (u32)(sizeof order / sizeof order[0])); + return first_fitting_type(p, v, order, + (u32)(sizeof order / sizeof order[0])); } if (!u && ll) { - static const TypeKind order[] = {TY_LLONG}; - return first_fitting_type(p, v, order, (u32)(sizeof order / sizeof order[0])); + static const TypeKind dec_order[] = {TY_LLONG}; + static const TypeKind other_order[] = {TY_LLONG, TY_ULLONG}; + return decimal ? first_fitting_type( + p, v, dec_order, + (u32)(sizeof dec_order / sizeof dec_order[0])) + : first_fitting_type( + p, v, other_order, + (u32)(sizeof other_order / sizeof other_order[0])); } if (u && l) { static const TypeKind order[] = {TY_ULONG, TY_ULLONG}; - return first_fitting_type(p, v, order, (u32)(sizeof order / sizeof order[0])); + return first_fitting_type(p, v, order, + (u32)(sizeof order / sizeof order[0])); } if (!u && l) { static const TypeKind dec_order[] = {TY_LONG, TY_LLONG}; static const TypeKind other_order[] = {TY_LONG, TY_ULONG, TY_LLONG, TY_ULLONG}; - return decimal ? first_fitting_type(p, v, dec_order, - (u32)(sizeof dec_order / - sizeof dec_order[0])) - : first_fitting_type(p, v, other_order, - (u32)(sizeof other_order / - sizeof other_order[0])); + return decimal ? first_fitting_type( + p, v, dec_order, + (u32)(sizeof dec_order / sizeof dec_order[0])) + : first_fitting_type( + p, v, other_order, + (u32)(sizeof other_order / sizeof other_order[0])); } if (u) { static const TypeKind order[] = {TY_UINT, TY_ULONG, TY_ULLONG}; - return first_fitting_type(p, v, order, (u32)(sizeof order / sizeof order[0])); + return first_fitting_type(p, v, order, + (u32)(sizeof order / sizeof order[0])); } if (decimal) { static const TypeKind order[] = {TY_INT, TY_LONG, TY_LLONG}; - return first_fitting_type(p, v, order, (u32)(sizeof order / sizeof order[0])); + return first_fitting_type(p, v, order, + (u32)(sizeof order / sizeof order[0])); } else { - static const TypeKind order[] = {TY_INT, TY_UINT, TY_LONG, + static const TypeKind order[] = {TY_INT, TY_UINT, TY_LONG, TY_ULONG, TY_LLONG, TY_ULLONG}; - return first_fitting_type(p, v, order, (u32)(sizeof order / sizeof order[0])); + return first_fitting_type(p, v, order, + (u32)(sizeof order / sizeof order[0])); } } @@ -423,13 +432,12 @@ CfreeCgSym emit_string_to_rodata(Parser* p, const u8* bytes, size_t n) { } CfreeCgSym emit_string_literal_to_rodata(Parser* p, const u8* bytes, - size_t nbytes, - const Type* elem_ty) { + size_t nbytes, const Type* elem_ty) { u32 elem_size = c_abi_sizeof(p->abi, elem_ty); u32 count = elem_size ? (u32)(nbytes / elem_size) : 0; const Type* arr_ty = type_array(p->pool, elem_ty, count, 0); - return cfree_cg_const_data(p->cg, bytes, nbytes, c_abi_alignof(p->abi, elem_ty), - pcg_tid(p, arr_ty)); + return cfree_cg_const_data( + p->cg, bytes, nbytes, c_abi_alignof(p->abi, elem_ty), pcg_tid(p, arr_ty)); } /* ============================================================ @@ -681,15 +689,15 @@ static CConstInt cexpr_mul(Parser* p, SrcLoc loc) { v = cint_mul(p, ct, v, r); } else { if (!cint_nonzero(r)) - compiler_panic(p->c, loc, op == '/' ? "division by zero in constant" - : "modulo by zero in constant"); + compiler_panic(p->c, loc, + op == '/' ? "division by zero in constant" + : "modulo by zero in constant"); if (cint_signed(p, ct)) { i64 lv = const_int_as_i64(p, v); i64 rv = const_int_as_i64(p, r); v = cint_make_u64(p, ct, op == '/' ? (u64)(lv / rv) : (u64)(lv % rv)); } else { - v = cint_make_u64(p, ct, - op == '/' ? v.lo / r.lo : v.lo % r.lo); + v = cint_make_u64(p, ct, op == '/' ? v.lo / r.lo : v.lo % r.lo); } } } @@ -775,13 +783,13 @@ static CConstInt cexpr_rel(Parser* p, SrcLoc loc) { if (cint_signed(p, ct)) { i64 lv = const_int_as_i64(p, v); i64 rv = const_int_as_i64(p, r); - res = op == P_LE ? lv <= rv + res = op == P_LE ? lv <= rv : op == P_GE ? lv >= rv : op == '<' ? lv < rv : lv > rv; } else { int cmp = cint_cmp_u(v, r); - res = op == P_LE ? cmp <= 0 + res = op == P_LE ? cmp <= 0 : op == P_GE ? cmp >= 0 : op == '<' ? cmp < 0 : cmp > 0; @@ -896,7 +904,8 @@ static CConstInt cexpr_unary(Parser* p, SrcLoc loc) { v = cint_convert(p, v, pt); return cint_bnot(p, pt, v); } - if (accept_punct(p, '!')) return cint_bool(p, !cint_truth(p, cexpr_unary(p, loc))); + if (accept_punct(p, '!')) + return cint_bool(p, !cint_truth(p, cexpr_unary(p, loc))); if (accept_kw(p, KW_SIZEOF)) { if (is_punct(&p->cur, '(')) { Tok n = peek1(p); @@ -994,7 +1003,8 @@ static CConstInt cexpr_unary(Parser* p, SrcLoc loc) { SymEntry* e = scope_lookup(p, name); if (e && e->kind == SEK_ENUM_CST) { advance(p); - return cint_make_u64(p, e->type ? e->type : ty_int(p), (u64)e->v.enum_value); + return cint_make_u64(p, e->type ? e->type : ty_int(p), + (u64)e->v.enum_value); } } compiler_panic(p->c, loc, "non-constant identifier in constant expression"); @@ -1850,7 +1860,8 @@ static void parse_primary(Parser* p) { const Type* elem_ty = string_literal_elem_type(p, &t); u32 elem_size = c_abi_sizeof(p->abi, elem_ty); ObjSymId sym = emit_string_literal_to_rodata(p, bytes, n, elem_ty); - cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0); + cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, + bytes, 0); advance(p); { const Type* arr_ty = @@ -1864,9 +1875,9 @@ static void parse_primary(Parser* p) { static int find_record_member_path(Parser* p, const Type* rec_ty, Sym mname, const Type** out_ty, u32 path[2], - u32* out_depth, - const Field** out_field) { + u32* out_depth, const Field** out_field) { const ABIRecordLayout* L; + rec_ty = type_unqual(p->pool, rec_ty); if (!rec_ty || (rec_ty->kind != TY_STRUCT && rec_ty->kind != TY_UNION)) return 0; L = c_abi_record_layout(p->abi, p->pool, rec_ty); @@ -1880,12 +1891,16 @@ static int find_record_member_path(Parser* p, const Type* rec_ty, Sym mname, if (out_field) *out_field = f; return 1; } - if ((f->flags & FIELD_ANON) && - (f->type->kind == TY_STRUCT || f->type->kind == TY_UNION)) { - const ABIRecordLayout* IL = c_abi_record_layout(p->abi, p->pool, f->type); + { + const Type* fty = type_unqual(p->pool, f->type); + if (!((f->flags & FIELD_ANON) && + (fty->kind == TY_STRUCT || fty->kind == TY_UNION))) { + continue; + } + const ABIRecordLayout* IL = c_abi_record_layout(p->abi, p->pool, fty); if (!IL) continue; - for (u16 j = 0; j < f->type->rec.nfields; ++j) { - const Field* ff = &f->type->rec.fields[j]; + for (u16 j = 0; j < fty->rec.nfields; ++j) { + const Field* ff = &fty->rec.fields[j]; if (ff->name == mname && mname != 0) { *out_ty = ff->type; path[0] = i; @@ -2053,6 +2068,7 @@ static void parse_postfix(Parser* p) { } mname = p->cur.v.ident; advance(p); + lt = type_unqual(p->pool, lt); if (!find_record_member_path(p, lt, mname, &mty, path, &depth, &mf)) perr(p, "no such member"); cg_record_member_path(p, mty, path, depth, mf); @@ -2072,7 +2088,7 @@ static void parse_postfix(Parser* p) { if (!lt0 || lt0->kind != TY_PTR) { perr(p, "'->' requires a pointer operand"); } - rec_ty = lt0->ptr.pointee; + rec_ty = type_unqual(p->pool, lt0->ptr.pointee); if (!rec_ty || (rec_ty->kind != TY_STRUCT && rec_ty->kind != TY_UNION)) { perr(p, "'->' on pointer to non-struct/union"); } @@ -2180,8 +2196,8 @@ void parse_unary(Parser* p) { if (is_punct(&t, '&')) { advance(p); parse_unary(p); - if (!pcg_top_is_lvalue(p) && !(cg_top_type(p->cg) && - cg_top_type(p->cg)->kind == TY_FUNC)) { + if (!pcg_top_is_lvalue(p) && + !(cg_top_type(p->cg) && cg_top_type(p->cg)->kind == TY_FUNC)) { perr(p, "address-of requires lvalue operand"); } if (pcg_top_is_bitfield(p)) perr(p, "cannot take address of bit-field"); @@ -2695,16 +2711,27 @@ static void parse_rel(Parser* p) { perr(p, "comparison of incompatible pointer types"); } } else if (!type_is_arith(lt) || !type_is_arith(rt)) { - perr(p, "relational operator requires arithmetic or compatible pointer operands"); + perr(p, + "relational operator requires arithmetic or compatible pointer " + "operands"); } if (common) { coerce_fp_cmp_operands(p, common); switch (cop) { - case CMP_LT_S: cop = CMP_LT_F; break; - case CMP_LE_S: cop = CMP_LE_F; break; - case CMP_GT_S: cop = CMP_GT_F; break; - case CMP_GE_S: cop = CMP_GE_F; break; - default: break; + case CMP_LT_S: + cop = CMP_LT_F; + break; + case CMP_LE_S: + cop = CMP_LE_F; + break; + case CMP_GT_S: + cop = CMP_GT_F; + break; + case CMP_GE_S: + cop = CMP_GE_F; + break; + default: + break; } } else if (type_is_arith(lt) && type_is_arith(rt)) { common = cint_common_type(p, lt, rt); @@ -2749,7 +2776,8 @@ static void parse_eq(Parser* p) { } else if (!type_is_arith(lt) || !type_is_arith(rt)) { perr(p, "equality operator requires scalar operands"); } - if (common) coerce_fp_cmp_operands(p, common); + if (common) + coerce_fp_cmp_operands(p, common); else if (type_is_arith(lt) && type_is_arith(rt)) { common = cint_common_type(p, lt, rt); coerce_arith_operands(p, common); @@ -2769,8 +2797,8 @@ static void parse_band(Parser* p) { if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { perr(p, "bitwise operator requires integer operands"); } - coerce_arith_operands(p, cint_common_type(p, cg_top2_type(p->cg), - cg_top_type(p->cg))); + coerce_arith_operands( + p, cint_common_type(p, cg_top2_type(p->cg), cg_top_type(p->cg))); cg_binop(p->cg, BO_AND); } } @@ -2785,8 +2813,8 @@ static void parse_bxor(Parser* p) { if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { perr(p, "bitwise operator requires integer operands"); } - coerce_arith_operands(p, cint_common_type(p, cg_top2_type(p->cg), - cg_top_type(p->cg))); + coerce_arith_operands( + p, cint_common_type(p, cg_top2_type(p->cg), cg_top_type(p->cg))); cg_binop(p->cg, BO_XOR); } } @@ -2801,8 +2829,8 @@ static void parse_bor(Parser* p) { if (!type_is_int(cg_top2_type(p->cg)) || !type_is_int(cg_top_type(p->cg))) { perr(p, "bitwise operator requires integer operands"); } - coerce_arith_operands(p, cint_common_type(p, cg_top2_type(p->cg), - cg_top_type(p->cg))); + coerce_arith_operands( + p, cint_common_type(p, cg_top2_type(p->cg), cg_top_type(p->cg))); cg_binop(p->cg, BO_OR); } } @@ -2959,9 +2987,8 @@ static void parse_ternary(Parser* p) { to_rvalue(p); const Type* else_ty = cg_top_type(p->cg); const Type* common = common_fp_type(p, result_ty, else_ty); - const Type* ptr_result = - conditional_pointer_type(p, result_ty, then_null, else_ty, - null_pointer_constant(p, else_ty)); + const Type* ptr_result = conditional_pointer_type( + p, result_ty, then_null, else_ty, null_pointer_constant(p, else_ty)); if ((result_ty && result_ty->kind == TY_PTR) || (else_ty && else_ty->kind == TY_PTR)) { if (!ptr_result) perr(p, "conditional operator pointer type mismatch"); @@ -3077,21 +3104,44 @@ void parse_assign_expr(Parser* p) { const Type* rhs = cg_top_type(p->cg); int op = '+'; switch (compound) { - case BO_IADD: op = '+'; break; - case BO_ISUB: op = '-'; break; - case BO_IMUL: op = '*'; break; - case BO_SDIV: op = '/'; break; - case BO_SREM: op = '%'; break; - case BO_AND: op = '&'; break; - case BO_OR: op = '|'; break; - case BO_XOR: op = '^'; break; - case BO_SHL: op = '<'; break; - case BO_SHR_S: op = '>'; break; - case BO_SHR_U: op = '>'; break; - default: op = 0; break; - } - CSemCheck chk = - c_sem_check_compound_assignment(p->pool, lhs, rhs, op); + case BO_IADD: + op = '+'; + break; + case BO_ISUB: + op = '-'; + break; + case BO_IMUL: + op = '*'; + break; + case BO_SDIV: + op = '/'; + break; + case BO_SREM: + op = '%'; + break; + case BO_AND: + op = '&'; + break; + case BO_OR: + op = '|'; + break; + case BO_XOR: + op = '^'; + break; + case BO_SHL: + op = '<'; + break; + case BO_SHR_S: + op = '>'; + break; + case BO_SHR_U: + op = '>'; + break; + default: + op = 0; + break; + } + CSemCheck chk = c_sem_check_compound_assignment(p->pool, lhs, rhs, op); if (!chk.ok) perr(p, "%s", chk.message); } if (compound == BO_IADD || compound == BO_ISUB) { diff --git a/lang/c/parse/parse_init.c b/lang/c/parse/parse_init.c @@ -244,7 +244,8 @@ static void init_string_at(Parser* p, FrameSlot slot, const Type* arr_ty, if (copy > count) copy = count; for (i = 0; i < copy; ++i) { push_subobject_lv(p, slot, arr_ty, offset + (u32)i * elem_size, elem_ty); - cg_push_int(p->cg, (i64)decode_lit_unit_le(bytes + i * elem_size, elem_size), + cg_push_int(p->cg, + (i64)decode_lit_unit_le(bytes + i * elem_size, elem_size), elem_ty); cg_store(p->cg); cg_drop(p->cg); @@ -255,7 +256,8 @@ static void init_string_at(Parser* p, FrameSlot slot, const Type* arr_ty, cg_store(p->cg); cg_drop(p->cg); } - cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0); + cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, + bytes, 0); advance(p); /* consume TOK_STR */ } @@ -369,8 +371,8 @@ static int aggregate_has_index(const Type* ty, u32 index) { } static int designator_continues_inside(Parser* p, const Type* outer_ty, - u32 outer_offset, - const Type* top_ty, u32 top_offset, + u32 outer_offset, const Type* top_ty, + u32 top_offset, const InitDesignatorCont* cont) { u32 top_size; if (!cont || !cont->parent_ty) return 0; @@ -395,8 +397,7 @@ static u32 init_struct_fields(Parser* p, FrameSlot slot, const Type* arr_ty, u32 sub_off; u32 top_idx = 0; InitDesignatorCont cont; - parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx, - &cont); + parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx, &cont); while (zero_lo < top_idx) { const Field* zf = &ty->rec.fields[zero_lo]; if (zf->flags & FIELD_BITFIELD) { @@ -549,8 +550,8 @@ void init_at(Parser* p, FrameSlot slot, const Type* arr_ty, u32 offset, ++zero_lo; } init_at(p, slot, arr_ty, sub_off, sub_ty); - if (designator_continues_inside( - p, ty, offset, elem_ty, offset + top_idx * esz, &cont) && + if (designator_continues_inside(p, ty, offset, elem_ty, + offset + top_idx * esz, &cont) && accept_punct(p, ',') && !is_punct(&p->cur, '}')) { init_aggregate_remainder(p, slot, arr_ty, cont.parent_offset, cont.parent_ty, cont.next_index); @@ -680,8 +681,7 @@ static void encode_binary128_from_double_le(u8 out[16], double value) { sign = (u32)(in.u >> 63); exp = (u32)((in.u >> 52) & 0x7ffu); frac = in.u & 0x000fffffffffffffull; - if (sign) - hi |= 1ull << 63; + if (sign) hi |= 1ull << 63; if (exp == 0x7ffu) { hi |= (u64)0x7fffu << 48; if (frac) { @@ -765,9 +765,8 @@ static int try_parse_static_float(Parser* p, u8* dst, u32 size, const Type* ty) { const Type* uty = type_unqual(p->pool, ty); double value; - if (!uty || - (uty->kind != TY_FLOAT && uty->kind != TY_DOUBLE && - uty->kind != TY_LDOUBLE)) { + if (!uty || (uty->kind != TY_FLOAT && uty->kind != TY_DOUBLE && + uty->kind != TY_LDOUBLE)) { return 0; } value = parse_static_float_add(p); @@ -811,7 +810,8 @@ static void parse_static_string_at(Parser* p, u8* buf, u32 buflen, u32 offset, if (offset + (u32)copy_bytes > buflen) perr(p, "string initializer overflows object"); memcpy(buf + offset, bytes, copy_bytes); - cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0); + cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, + bytes, 0); advance(p); } @@ -1026,7 +1026,8 @@ static int try_parse_static_address_const(Parser* p, CStaticConst* out) { u8* bytes = decode_string_literal(p, &t, &n); const Type* elem_ty = string_literal_elem_type(p, &t); ObjSymId str_sym = emit_string_literal_to_rodata(p, bytes, n, elem_ty); - cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, bytes, 0); + cfree_compiler_context(p->c)->heap->free(cfree_compiler_context(p->c)->heap, + bytes, 0); advance(p); out->kind = C_STATIC_CONST_ADDR; out->target = str_sym; @@ -1109,6 +1110,15 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) { if (ty && ty->kind == TY_PTR) { if (is_punct(&p->cur, '(')) { Tok n = peek1(p); + if (is_punct(&n, '(')) { + advance(p); + r = parse_static_const(p, ty, loc); + expect_punct(p, ')', "')' in static pointer initializer"); + return r; + } + } + if (is_punct(&p->cur, '(')) { + Tok n = peek1(p); if (starts_type_name(p, &n)) { const Type* cast_ty; const Type* cast_unqual; @@ -1129,7 +1139,19 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) { !type_is_int(cast_unqual))) { perr(p, "invalid cast in null pointer constant"); } + if (cast_unqual->kind == TY_PTR && + (p->cur.kind == TOK_STR || is_punct(&p->cur, '&') || + (p->cur.kind == TOK_IDENT && + ident_kw_init(p, p->cur.v.ident) == KW_NONE)) && + try_parse_static_address_const(p, &r)) { + return r; + } r.int_value = parse_null_pointer_constant(p, loc); + if (const_int_as_i64(p, r.int_value) != 0 && + cast_unqual->kind == TY_PTR) { + r.kind = C_STATIC_CONST_INT; + return r; + } if (const_int_as_i64(p, r.int_value) != 0) { perr(p, "static pointer initializer is not a null pointer constant"); } @@ -1151,8 +1173,7 @@ static CStaticConst parse_static_const(Parser* p, const Type* ty, SrcLoc loc) { } static void parse_static_bitfield_at(Parser* p, u8* buf, u32 buflen, - u32 rec_offset, - const ABIFieldLayout* fl, + u32 rec_offset, const ABIFieldLayout* fl, const Type* field_ty) { SrcLoc cloc = tok_loc_init(&p->cur); CStaticConst parsed = parse_static_const(p, field_ty, cloc); @@ -1254,8 +1275,8 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset, parse_designator_chain(p, ty, offset, &sub_ty, &sub_off, &top_idx, &cont); parse_static_init_at(p, buf, buflen, sub_off, sub_ty); - if (designator_continues_inside( - p, ty, offset, elem, offset + top_idx * esz, &cont) && + if (designator_continues_inside(p, ty, offset, elem, + offset + top_idx * esz, &cont) && accept_punct(p, ',') && !is_punct(&p->cur, '}')) { parse_static_aggregate_remainder(p, buf, buflen, cont.parent_offset, cont.parent_ty, cont.next_index); @@ -1299,9 +1320,8 @@ void parse_static_init_at(Parser* p, u8* buf, u32 buflen, u32 offset, if (designator_continues_inside(p, ty, offset, top_f->type, top_off, &cont) && accept_punct(p, ',') && !is_punct(&p->cur, '}')) { - parse_static_aggregate_remainder( - p, buf, buflen, cont.parent_offset, cont.parent_ty, - cont.next_index); + parse_static_aggregate_remainder(p, buf, buflen, cont.parent_offset, + cont.parent_ty, cont.next_index); } } i = top_idx + 1; diff --git a/lang/c/type/type.c b/lang/c/type/type.c @@ -302,6 +302,15 @@ const Type* type_unqual(Pool* p, const Type* t) { return type_prim(p, (TypeKind)t->kind); c = cache_get(p); if (!c) return NULL; + if ((t->kind == TY_STRUCT || t->kind == TY_UNION) && + t->rec.tag_id != TAG_NONE) { + for (TypeListNode* n = c->derived; n; n = n->next) { + if (n->ty.kind == t->kind && n->ty.qual == 0 && + n->ty.rec.tag_id == t->rec.tag_id && !n->ty.rec.incomplete) { + return &n->ty; + } + } + } tmpl = *t; tmpl.qual = 0; for (TypeListNode* n = c->derived; n; n = n->next) { diff --git a/test/parse/cases/6_4_4_1_hex_ll_unsigned_fallback.c b/test/parse/cases/6_4_4_1_hex_ll_unsigned_fallback.c @@ -0,0 +1,5 @@ +typedef unsigned long long u64; +int test_main(void) { + u64 x = 0xfffffffffc000000LL; + return (x & 0x04000000ULL) ? 42 : 1; +} diff --git a/test/parse/cases/6_4_4_1_hex_ll_unsigned_fallback.expected b/test/parse/cases/6_4_4_1_hex_ll_unsigned_fallback.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_5_3_2_04_call_deref_function_pointer.c b/test/parse/cases/6_5_3_2_04_call_deref_function_pointer.c @@ -0,0 +1,11 @@ +typedef int (*Fn)(int); + +static int add1(int x) { return x + 1; } + +static int call_it(Fn f, int x) { + return (*f)(x); +} + +int test_main(void) { + return call_it(add1, 41); +} diff --git a/test/parse/cases/6_5_3_2_04_call_deref_function_pointer.expected b/test/parse/cases/6_5_3_2_04_call_deref_function_pointer.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_6_12_cast_addr_const_static_init.c b/test/parse/cases/6_6_12_cast_addr_const_static_init.c @@ -0,0 +1,6 @@ +static int g = 7; +struct S { + void* p; +}; +static struct S table[] = {{(void*)&g}}; +int test_main(void) { return *(int*)table[0].p * 6; } diff --git a/test/parse/cases/6_6_12_cast_addr_const_static_init.expected b/test/parse/cases/6_6_12_cast_addr_const_static_init.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_7_2_3_03_qualified_forward_member.c b/test/parse/cases/6_7_2_3_03_qualified_forward_member.c @@ -0,0 +1,10 @@ +struct S; +struct Holder { + const struct S* p; +}; +struct S { + int x; +}; +static const struct S value = {42}; +static struct Holder holder = {&value}; +int test_main(void) { return holder.p->x; } diff --git a/test/parse/cases/6_7_2_3_03_qualified_forward_member.expected b/test/parse/cases/6_7_2_3_03_qualified_forward_member.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_7_9_32_static_ptr_cast_nonzero_int.c b/test/parse/cases/6_7_9_32_static_ptr_cast_nonzero_int.c @@ -0,0 +1,2 @@ +static void* p = ((void*)(long)1); +int test_main(void) { return p != 0 ? 42 : 1; } diff --git a/test/parse/cases/6_7_9_32_static_ptr_cast_nonzero_int.expected b/test/parse/cases/6_7_9_32_static_ptr_cast_nonzero_int.expected @@ -0,0 +1 @@ +42 diff --git a/test/parse/cases/6_7_9_33_static_struct_ptr_cast_nonzero_int.c b/test/parse/cases/6_7_9_33_static_struct_ptr_cast_nonzero_int.c @@ -0,0 +1,9 @@ +struct F { + int n; + void* p; + void (*fn)(void); + const char* name; +}; +static void noop(void) {} +static struct F funcs[] = {{2, (void*)(long)1, noop, "x"}}; +int test_main(void) { return funcs[0].p != 0 && funcs[0].fn != 0 ? 42 : 1; } diff --git a/test/parse/cases/6_7_9_33_static_struct_ptr_cast_nonzero_int.expected b/test/parse/cases/6_7_9_33_static_struct_ptr_cast_nonzero_int.expected @@ -0,0 +1 @@ +42