commit 7f8eab153bbe7861f2466909b1e0b71ad9488730
parent aaf3e90b91d0938e78ff4af28c7fdc52f12bc3c4
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 10 Jun 2026 07:49:36 -0700
cleanup: I.3 — add pcg_retag_keep_flags op for shadow-stack retags
Two parse_expr.c sites poked p->cg_type_stack[...] directly to change a
slot's type while keeping its value flags + lvalue aux (struct
unqualification; narrowing a compound-assign LHS) because no op expressed
that. Add pcg_retag_keep_flags(p, depth, ty) and route both sites through
it. Semantically identical (same array write); removes the bridge poke.
test-parse (3880+128), test-cg-api (211), test-toy (1394/0/33) green.
Diffstat:
4 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/doc/plan/TODO.md b/doc/plan/TODO.md
@@ -109,8 +109,6 @@ Add new deferred fixes below as they are discovered.
bridge — higher risk; needs care.)
- **I.2 — two parallel C-6.7.9 initializer walkers** (`lang/c/parse/parse_init.c:648-777`)
re-encode the same traversal grammar. Factor a single grammar driver + leaf vtable.
-- **I.3 — `cg_adapter` callers poke the shadow-stack array directly** because no
- retag-keep-flags op exists. Add the op. (Pairs with I.1.)
- **I.4 — opt passes re-hand-roll the centralized operand-walk.** (The `ranges_overlap`
trampoline part is fixed.)
diff --git a/lang/c/parse/cg_adapter.c b/lang/c/parse/cg_adapter.c
@@ -183,6 +183,15 @@ void pcg_retag_top(Parser* p, const Type* ty) {
}
}
+/* Replace the type of the slot `depth` below the top (depth 0 == top) while
+ * preserving its value flags and lvalue aux. Unlike pcg_retag_top this keeps
+ * the slot's lvalue-ness/bitfield/aux intact — used where only the C type
+ * changes (e.g. struct unqualification, narrowing a compound-assign LHS). */
+void pcg_retag_keep_flags(Parser* p, u32 depth, const Type* ty) {
+ if (p->cg_type_sp > depth)
+ p->cg_type_stack[p->cg_type_sp - 1u - depth] = ty;
+}
+
int pcg_top_is_bitfield(Parser* p) {
return p->cg_type_sp &&
(p->cg_value_flags[p->cg_type_sp - 1u] & PCG_VALUE_BITFIELD) != 0;
diff --git a/lang/c/parse/cg_adapter.h b/lang/c/parse/cg_adapter.h
@@ -237,6 +237,7 @@ KitCgMemAccess pcg_mem(Parser*, const Type*);
const Type* pcg_top_type(Parser*);
const Type* pcg_top2_type(Parser*);
void pcg_retag_top(Parser*, const Type*);
+void pcg_retag_keep_flags(Parser*, u32 depth, const Type*);
void pcg_push_type(Parser*, const Type*);
void pcg_drop_type(Parser*);
void pcg_dup_type(Parser*);
diff --git a/lang/c/parse/parse_expr.c b/lang/c/parse/parse_expr.c
@@ -1033,7 +1033,7 @@ void to_rvalue(Parser* p) {
is_lvalue && lv &&
(lv->offset != 0 || lv->scale != 0 || lv->is_subobject ||
lv->base_kind == PCG_LV_BASE_POINTER_RV);
- p->cg_type_stack[p->cg_type_sp - 1u] = uty;
+ pcg_retag_keep_flags(p, 0, uty);
if (materialize) {
pcg_addr(p);
pcg_deref(p, uty);
@@ -3536,7 +3536,7 @@ void parse_assign_expr(Parser* p) {
}
}
coerce_top_to_type(p, lhs);
- if (p->cg_type_sp >= 2) p->cg_type_stack[p->cg_type_sp - 2u] = lhs;
+ pcg_retag_keep_flags(p, 1, lhs);
pcg_store(p);
}