lowering: .n 은 슬라이스에게만 길이다
구조체도 필드를 n 이라 부를 수 있다. lowering 은 이름만 보고 슬라이스 길이
자리(포인터 다음 4바이트)를 읽어서, 그 자리에 있던 그럴듯한 숫자를 돌려주고
있었다. 체커는 제대로 필드로 풀고 있었으니 같은 함수 안에서 쓰기와 읽기가
어긋났다.
Box{ room: ^[]mut u8, n: usize, m: usize }
n 777 m 999 (전에는 n 12 -- room 의 길이)
배열/슬라이스/str 일 때만 길이로 읽는다. fieldn.fe 가 이것과, 옆의 슬라이스가
여전히 길이로 답하는 것을 함께 고정한다.
222/222, 30/30.
This commit is contained in:
+9
-3
@@ -151,9 +151,15 @@ Slot lower_expr_core(Lower *L, FeNode *n)
|
|||||||
return slot_place(fe_ir_at_temp(p, 0), it, ir_size(t));
|
return slot_place(fe_ir_at_temp(p, 0), it, ir_size(t));
|
||||||
}
|
}
|
||||||
/* `.n` is how many elements there are, which an array knows at
|
/* `.n` is how many elements there are, which an array knows at
|
||||||
compile time and a slice carries beside its pointer. */
|
compile time and a slice carries beside its pointer. Only for those:
|
||||||
if (n->b && n->b->text && !strcmp(n->b->text, "n")) {
|
a struct is free to have a field called `n`, and reading it as a
|
||||||
FeType *bt = n->a ? n->a->sem_type : 0;
|
length would quietly hand back the wrong four bytes. */
|
||||||
|
if (n->b && n->b->text && !strcmp(n->b->text, "n") &&
|
||||||
|
n->a && n->a->sem_type &&
|
||||||
|
(n->a->sem_type->kind == FE_TYPE_ARRAY ||
|
||||||
|
n->a->sem_type->kind == FE_TYPE_SLICE ||
|
||||||
|
n->a->sem_type->kind == FE_TYPE_STR)) {
|
||||||
|
FeType *bt = n->a->sem_type;
|
||||||
Slot base;
|
Slot base;
|
||||||
if (bt && bt->kind == FE_TYPE_ARRAY)
|
if (bt && bt->kind == FE_TYPE_ARRAY)
|
||||||
return slot_value(fe_ir_const(L->m, L->b, FE_IR_I32,
|
return slot_value(fe_ir_const(L->m, L->b, FE_IR_I32,
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// EXIT:0
|
||||||
|
// OUTPUT:n 777 m 999
|
||||||
|
// OUTPUT:len 12 first 7
|
||||||
|
// OUTPUT:count 3
|
||||||
|
// OUTPUT:balanced
|
||||||
|
unit fieldn;
|
||||||
|
|
||||||
|
import std.io;
|
||||||
|
import std.sys;
|
||||||
|
import std.mem;
|
||||||
|
|
||||||
|
// `.n` on a slice is its length. On a struct it is whatever field is called
|
||||||
|
// `n` -- and a struct is allowed to call a field that. Reading one as the
|
||||||
|
// other hands back the four bytes beside the pointer, which is a plausible
|
||||||
|
// number and so goes unnoticed.
|
||||||
|
|
||||||
|
struct Box {
|
||||||
|
room: ^[]mut u8,
|
||||||
|
n: usize,
|
||||||
|
m: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Counter {
|
||||||
|
n: usize,
|
||||||
|
|
||||||
|
fn bump(self: &mut Self) -> void { self.n = self.n + 1; return; }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run() -> !void {
|
||||||
|
let r: ^[]mut u8 = try mem.alloc_slice(u8, 12);
|
||||||
|
r.^[0] = 7;
|
||||||
|
let b: Box = Box{ room: r, n: 777, m: 999 };
|
||||||
|
@print("n {} m {}\n", b.n, b.m);
|
||||||
|
// The slice beside it still answers with its length.
|
||||||
|
@print("len {} first {}\n", b.room.^.n, b.room.^[0]);
|
||||||
|
var c: Counter = Counter{ n: 0 };
|
||||||
|
c.bump();
|
||||||
|
c.bump();
|
||||||
|
c.bump();
|
||||||
|
@print("count {}\n", c.n);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> i32 {
|
||||||
|
run() catch |e| { @print("failed\n"); return 1; };
|
||||||
|
if sys.allocs() == sys.frees() { @print("balanced\n"); }
|
||||||
|
else { @print("leaked\n"); }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user