📄 decl.c
字号:
foreach(identifiers, level, checkref, NULL);
if (!IR->wants_callb && isstruct(rty)) {
Symbol *a;
a = newarray(n + 2, sizeof *a, FUNC);
a[0] = retv;
memcpy(&a[1], callee, (n+1)*sizeof *callee);
callee = a;
a = newarray(n + 2, sizeof *a, FUNC);
NEW(a[0], FUNC);
*a[0] = *retv;
memcpy(&a[1], caller, (n+1)*sizeof *callee);
caller = a;
}
if (!IR->wants_argb)
for (i = 0; caller[i]; i++)
if (isstruct(caller[i]->type)) {
caller[i]->type = ptr(caller[i]->type);
callee[i]->type = ptr(callee[i]->type);
caller[i]->structarg = callee[i]->structarg = 1;
}
if (glevel > 1) for (i = 0; callee[i]; i++) callee[i]->sclass = AUTO;
if (cfunc->sclass != STATIC)
(*IR->export)(cfunc);
if (glevel && IR->stabsym) {
swtoseg(CODE); (*IR->stabsym)(cfunc); }
swtoseg(CODE);
(*IR->function)(cfunc, caller, callee, cfunc->u.f.ncalls);
if (glevel && IR->stabfend)
(*IR->stabfend)(cfunc, lineno);
foreach(stmtlabs, LABELS, checklab, NULL);
exitscope();
expect('}');
labels = stmtlabs = NULL;
retv = NULL;
cfunc = NULL;
}
static void oldparam(Symbol p, void *cl) {
int i;
Symbol *callee = cl;
for (i = 0; callee[i]; i++)
if (p->name == callee[i]->name) {
callee[i] = p;
return;
}
error("declared parameter `%s' is missing\n", p->name);
}
void compound(int loop, struct swtch *swp, int lev) {
Code cp;
int nregs;
walk(NULL, 0, 0);
cp = code(Blockbeg);
enterscope();
assert(level >= LOCAL);
if (level == LOCAL && events.entry)
apply(events.entry, cfunc, NULL);
definept(NULL);
expect('{');
autos = registers = NULL;
if (level == LOCAL && IR->wants_callb
&& isstruct(freturn(cfunc->type))) {
retv = genident(AUTO, ptr(unqual(freturn(cfunc->type))), level);
retv->defined = 1;
retv->ref = 1;
registers = append(retv, registers);
}
while (kind[t] == CHAR || kind[t] == STATIC
|| istypename(t, tsym) && getchr() != ':')
decl(dcllocal);
{
int i;
Symbol *a = ltov(&autos, STMT);
nregs = length(registers);
for (i = 0; a[i]; i++)
registers = append(a[i], registers);
cp->u.block.locals = ltov(®isters, FUNC);
}
if (events.blockentry)
apply(events.blockentry, cp->u.block.locals, NULL);
while (kind[t] == IF || kind[t] == ID)
statement(loop, swp, lev);
walk(NULL, 0, 0);
foreach(identifiers, level, checkref, NULL);
{
int i = nregs, j;
Symbol p;
for ( ; (p = cp->u.block.locals[i]) != NULL; i++) {
for (j = i; j > nregs
&& cp->u.block.locals[j-1]->ref < p->ref; j--)
cp->u.block.locals[j] = cp->u.block.locals[j-1];
cp->u.block.locals[j] = p;
}
}
if (level == LOCAL) {
Code cp;
for (cp = codelist; cp->kind < Label; cp = cp->prev)
;
if (cp->kind != Jump) {
if (freturn(cfunc->type) != voidtype) {
warning("missing return value\n");
retcode(cnsttree(inttype, 0L));
} else
retcode(NULL);
}
}
if (events.blockexit)
apply(events.blockexit, cp->u.block.locals, NULL);
cp->u.block.level = level;
cp->u.block.identifiers = identifiers;
cp->u.block.types = types;
code(Blockend)->u.begin = cp;
if (reachable(Gen))
definept(NULL);
if (level > LOCAL) {
exitscope();
expect('}');
}
}
static void checkref(Symbol p, void *cl) {
if (p->scope >= PARAM
&& (isvolatile(p->type) || isfunc(p->type)))
p->addressed = 1;
if (Aflag >= 2 && p->defined && p->ref == 0) {
if (p->sclass == STATIC)
warning("static `%t %s' is not referenced\n",
p->type, p->name);
else if (p->scope == PARAM)
warning("parameter `%t %s' is not referenced\n",
p->type, p->name);
else if (p->scope >= LOCAL && p->sclass != EXTERN)
warning("local `%t %s' is not referenced\n",
p->type, p->name);
}
if (p->sclass == AUTO
&& (p->scope == PARAM && regcount == 0
|| p->scope >= LOCAL)
&& !p->addressed && isscalar(p->type) && p->ref >= 3.0)
p->sclass = REGISTER;
if (level == GLOBAL && p->sclass == STATIC && !p->defined
&& isfunc(p->type) && p->ref)
error("undefined static `%t %s'\n", p->type, p->name);
assert(!(level == GLOBAL && p->sclass == STATIC && !p->defined && !isfunc(p->type)));
}
static Symbol dcllocal(int sclass, char *id, Type ty, Coordinate *pos) {
Symbol p, q;
if (sclass == 0)
sclass = isfunc(ty) ? EXTERN : AUTO;
else if (isfunc(ty) && sclass != EXTERN) {
error("invalid storage class `%k' for `%t %s'\n",
sclass, ty, id);
sclass = EXTERN;
} else if (sclass == REGISTER
&& (isvolatile(ty) || isstruct(ty) || isarray(ty))) {
warning("register declaration ignored for `%t %s'\n",
ty, id);
sclass = AUTO;
}
q = lookup(id, identifiers);
if (q && q->scope >= level
|| q && q->scope == PARAM && level == LOCAL)
if (sclass == EXTERN && q->sclass == EXTERN
&& eqtype(q->type, ty, 1))
ty = compose(ty, q->type);
else
error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src);
assert(level >= LOCAL);
p = install(id, &identifiers, level, sclass == STATIC || sclass == EXTERN ? PERM : FUNC);
p->type = ty;
p->sclass = sclass;
p->src = *pos;
switch (sclass) {
case EXTERN: q = lookup(id, globals);
if (q == NULL || q->sclass == TYPEDEF || q->sclass == ENUM) {
q = lookup(id, externals);
if (q == NULL) {
q = install(p->name, &externals, GLOBAL, PERM);
q->type = p->type;
q->sclass = EXTERN;
q->src = src;
(*IR->defsymbol)(q);
}
}
if (!eqtype(p->type, q->type, 1))
warning("declaration of `%s' does not match previous declaration at %w\n", q->name, &q->src);
p->u.alias = q; break;
case STATIC: (*IR->defsymbol)(p);
initglobal(p, 0);
if (!p->defined)
if (p->type->size > 0) {
defglobal(p, BSS);
(*IR->space)(p->type->size);
} else
error("undefined size for `%t %s'\n",
p->type, p->name);
p->defined = 1; break;
case REGISTER: registers = append(p, registers);
regcount++;
p->defined = 1;
break;
case AUTO: autos = append(p, autos);
p->defined = 1;
if (isarray(ty))
p->addressed = 1; break;
default: assert(0);
}
if (t == '=') {
Tree e;
if (sclass == EXTERN)
error("illegal initialization of `extern %s'\n", id);
t = gettok();
definept(NULL);
if (isscalar(p->type)
|| isstruct(p->type) && t != '{') {
if (t == '{') {
t = gettok();
e = expr1(0);
expect('}');
} else
e = expr1(0);
} else {
Symbol t1;
Type ty = p->type, ty1 = ty;
while (isarray(ty1))
ty1 = ty1->type;
if (!isconst(ty) && (!isarray(ty) || !isconst(ty1)))
ty = qual(CONST, ty);
t1 = genident(STATIC, ty, GLOBAL);
initglobal(t1, 1);
if (isarray(p->type) && p->type->size == 0
&& t1->type->size > 0)
p->type = array(p->type->type,
t1->type->size/t1->type->type->size, 0);
e = idtree(t1);
}
walk(root(asgn(p, e)), 0, 0);
p->ref = 1;
}
if (!isfunc(p->type) && p->defined && p->type->size <= 0)
error("undefined size for `%t %s'\n", p->type, id);
return p;
}
void finalize(void) {
foreach(externals, GLOBAL, doextern, NULL);
foreach(identifiers, GLOBAL, doglobal, NULL);
foreach(identifiers, GLOBAL, checkref, NULL);
foreach(constants, CONSTANTS, doconst, NULL);
}
static void doextern(Symbol p, void *cl) {
(*IR->import)(p);
}
static void doglobal(Symbol p, void *cl) {
if (!p->defined && (p->sclass == EXTERN
|| isfunc(p->type) && p->sclass == AUTO))
(*IR->import)(p);
else if (!p->defined && !isfunc(p->type)
&& (p->sclass == AUTO || p->sclass == STATIC)) {
if (isarray(p->type)
&& p->type->size == 0 && p->type->type->size > 0)
p->type = array(p->type->type, 1, 0);
if (p->type->size > 0) {
defglobal(p, BSS);
(*IR->space)(p->type->size);
if (glevel > 0 && IR->stabsym)
(*IR->stabsym)(p);
} else
error("undefined size for `%t %s'\n",
p->type, p->name);
p->defined = 1;
}
if (Pflag
&& !isfunc(p->type)
&& !p->generated && p->sclass != EXTERN)
printdecl(p, p->type);
}
void doconst(Symbol p, void *cl) {
if (p->u.c.loc) {
assert(p->u.c.loc->u.seg == 0);
defglobal(p->u.c.loc, LIT);
if (isarray(p->type) && p->type->type == widechar) {
unsigned int *s = p->u.c.v.p;
int n = p->type->size/widechar->size;
while (n-- > 0) {
Value v;
v.u = *s++;
(*IR->defconst)(widechar->op, widechar->size, v);
}
} else if (isarray(p->type))
(*IR->defstring)(p->type->size, p->u.c.v.p);
else
(*IR->defconst)(p->type->op, p->type->size, p->u.c.v);
p->u.c.loc = NULL;
}
}
void checklab(Symbol p, void *cl) {
if (!p->defined)
error("undefined label `%s'\n", p->name);
p->defined = 1;
}
Type enumdcl(void) {
char *tag;
Type ty;
Symbol p;
Coordinate pos;
t = gettok();
pos = src;
if (t == ID) {
tag = token;
t = gettok();
} else
tag = "";
if (t == '{') {
static char follow[] = { IF, 0 };
int n = 0;
long k = -1;
List idlist = 0;
ty = newstruct(ENUM, tag);
t = gettok();
if (t != ID)
error("expecting an enumerator identifier\n");
while (t == ID) {
char *id = token;
Coordinate s;
if (tsym && tsym->scope == level)
error("redeclaration of `%s' previously declared at %w\n",
token, &tsym->src);
s = src;
t = gettok();
if (t == '=') {
t = gettok();
k = intexpr(0, 0);
} else {
if (k == inttype->u.sym->u.limits.max.i)
error("overflow in value for enumeration constant `%s'\n", id);
k++;
}
p = install(id, &identifiers, level, level < LOCAL ? PERM : FUNC);
p->src = s;
p->type = ty;
p->sclass = ENUM;
p->u.value = k;
idlist = append(p, idlist);
n++;
if (Aflag >= 2 && n == 128)
warning("more than 127 enumeration constants in `%t'\n", ty);
if (t != ',')
break;
t = gettok();
if (Aflag >= 2 && t == '}')
warning("non-ANSI trailing comma in enumerator list\n");
}
test('}', follow);
ty->type = inttype;
ty->size = ty->type->size;
ty->align = ty->type->align;
ty->u.sym->u.idlist = ltov(&idlist, PERM);
ty->u.sym->defined = 1;
} else if ((p = lookup(tag, types)) != NULL && p->type->op == ENUM) {
ty = p->type;
if (t == ';')
error("empty declaration\n");
} else {
error("unknown enumeration `%s'\n", tag);
ty = newstruct(ENUM, tag);
ty->type = inttype;
}
if (*tag && xref)
use(p, pos);
return ty;
}
Type typename(void) {
Type ty = specifier(NULL);
if (t == '*' || t == '(' || t == '[') {
ty = dclr(ty, NULL, NULL, 1);
if (Aflag >= 1 && !hasproto(ty))
warning("missing prototype\n");
}
return ty;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -