好像发现LCC编译器的一个BUG。。。
先贴出代码(注意红色的部分!):
Symbol install(const char *name, Table *tpp, int level, int arena) {
Table tp = *tpp;
struct entry *p;
unsigned h = (unsigned long)name&(HASHSIZE-1);
assert(level == 0 || level >= tp->level);
if (level > 0 && tp->level < level)
tp = *tpp = table(tp, level);
NEW0(p, arena);
p->sym.name = (char *)name;
p->sym.scope = level;
p->sym.up = tp->all;
tp->all = &p->sym;
p->link = tp->buckets[h];
tp->buckets[h] = p;
return &p->sym;
}
在看《可变目标C编译器》书上介绍这个函数时说:当level为0时表示,name应该建立在*tpp指向的表格中。
可是在代码里,红色那句的赋值,直接把0赋值给了符号的scope域。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
作者给我回信了。原文如下:
It's been a long time since I've looked at the lcc code...!
Passing 0 as level to install is used for labels within a function, e.g., see stmtlabel in src/stmt.c. You'll see that the scope for the symbol is set to LABELS immediately after the call to install.
We pass 0 as level to ensure that a new symbol table is not allocated, because it's not need for statement labels.
Your fix will work, but it's unnecessary because the scope is set explicitly (to LABELS) in all calls to install with level equal to 0.
Good to hear you enjoy lcc and the book,
thanks,
dave hanson
看来确实有bug,不过没有必要~~~
It's been a long time since I've looked at the lcc code...!
有位朋友的邮件,倒是提醒了我。其实如果想分析编译器实现,倒不如看看最初的gcc源代码,参见http://code.google.com/p/oldbison。
回复 4# yangnas
了解。
level为0时似乎总是label,当调用install且参数level为0,*tpp为stmtlabel,在调用完install后会始终将sym.scope修改为LABELS,stmt.c这个文件里面有
本帖最后由 yangnas 于 2010-10-14 06:22 编辑
回复 3# Guang-Yuan.Wang
我没有说参数level一定是0,我的意思是如果调用这样函数时level为0.
楼上,如果我调用这个函数时,参数level为0,那么在红色那行就直接把0赋值给了p->sym.scope了。
注意这个文件里有两个level变量,一个是全局的level变量(代表当前级别),还有一个,就是这个函数里的参数level
显然在红色这行的level应该是参数level。。。
回复 1# yangnas
哪里有说level一定是0,不是还有 level >= tp->level ?
这里 level 为 0 表示就在 *tpp 指向的符号表记录名字为 name 的符号,如果 level >= tp->level 表示有新的命名空间,应该分配新的table,比如遇到了 { }。
给作者写信,他现在在MS。