📄 decl.c
字号:
default: assert(0);
}
return ty;
}
static Symbol *parameters(Type fty) {
List list = NULL;
Symbol *params;
if (kind[t] == STATIC || istypename(t, tsym)) {
int n = 0;
Type ty1 = NULL;
for (;;) {
Type ty;
int sclass = 0;
char *id = NULL;
if (ty1 && t == ELLIPSIS) {
static struct symbol sentinel;
if (sentinel.type == NULL) {
sentinel.type = voidtype;
sentinel.defined = 1;
}
if (ty1 == voidtype)
error("illegal formal parameter types\n");
list = append(&sentinel, list);
t = gettok();
break;
}
if (!istypename(t, tsym) && t != REGISTER)
error("missing parameter type\n");
n++;
ty = dclr(specifier(&sclass), &id, NULL, 1);
if ( ty == voidtype && (ty1 || id)
|| ty1 == voidtype)
error("illegal formal parameter types\n");
if (id == NULL)
id = stringd(n);
if (ty != voidtype)
list = append(dclparam(sclass, id, ty, &src), list);
if (Aflag >= 1 && !hasproto(ty))
warning("missing prototype\n");
if (ty1 == NULL)
ty1 = ty;
if (t != ',')
break;
t = gettok();
}
fty->u.f.proto = newarray(length(list) + 1,
sizeof (Type *), PERM);
params = ltov(&list, FUNC);
for (n = 0; params[n]; n++)
fty->u.f.proto[n] = params[n]->type;
fty->u.f.proto[n] = NULL;
fty->u.f.oldstyle = 0;
} else {
if (t == ID)
for (;;) {
Symbol p;
if (t != ID) {
error("expecting an identifier\n");
break;
}
p = dclparam(0, token, inttype, &src);
p->defined = 0;
list = append(p, list);
t = gettok();
if (t != ',')
break;
t = gettok();
}
params = ltov(&list, FUNC);
fty->u.f.proto = NULL;
fty->u.f.oldstyle = 1;
}
if (t != ')') {
static char stop[] = { CHAR, STATIC, IF, ')', 0 };
expect(')');
skipto('{', stop);
}
if (t == ')')
t = gettok();
return params;
}
static void exitparams(Symbol params[]) {
assert(params);
if (params[0] && !params[0]->defined)
error("extraneous old-style parameter list\n");
if (level > PARAM)
exitscope();
exitscope();
}
static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) {
Symbol p;
if (isfunc(ty))
ty = ptr(ty);
else if (isarray(ty))
ty = atop(ty);
if (sclass == 0)
sclass = AUTO;
else if (sclass != REGISTER) {
error("invalid storage class `%k' for `%t%s\n",
sclass, ty, stringf(id ? " %s'" : "' parameter", id));
sclass = AUTO;
} else if (isvolatile(ty) || isstruct(ty)) {
warning("register declaration ignored for `%t%s\n",
ty, stringf(id ? " %s'" : "' parameter", id));
sclass = AUTO;
}
p = lookup(id, identifiers);
if (p && p->scope == level)
error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src);
else
p = install(id, &identifiers, level, FUNC);
p->sclass = sclass;
p->src = *pos;
p->type = ty;
p->defined = 1;
if (t == '=') {
error("illegal initialization for parameter `%s'\n", id);
t = gettok();
(void)expr1(0);
}
return p;
}
static Type structdcl(int op) {
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 stop[] = { IF, ',', 0 };
ty = newstruct(op, tag);
ty->u.sym->src = pos;
ty->u.sym->defined = 1;
t = gettok();
if (istypename(t, tsym))
fields(ty);
else
error("invalid %k field declarations\n", op);
test('}', stop);
}
else if (*tag && (p = lookup(tag, types)) != NULL
&& p->type->op == op) {
ty = p->type;
if (t == ';' && p->scope < level)
ty = newstruct(op, tag);
}
else {
if (*tag == 0)
error("missing %k tag\n", op);
ty = newstruct(op, tag);
}
if (*tag && xref)
use(ty->u.sym, pos);
return ty;
}
static void fields(Type ty) {
{ int n = 0;
while (istypename(t, tsym)) {
static char stop[] = { IF, CHAR, '}', 0 };
Type ty1 = specifier(NULL);
for (;;) {
Field p;
char *id = NULL;
Type fty = dclr(ty1, &id, NULL, 0);
p = newfield(id, ty, fty);
if (Aflag >= 1 && !hasproto(p->type))
warning("missing prototype\n");
if (t == ':') {
if (unqual(p->type) != inttype
&& unqual(p->type) != unsignedtype) {
error("`%t' is an illegal bit-field type\n",
p->type);
p->type = inttype;
}
t = gettok();
p->bitsize = intexpr(0, 0);
if (p->bitsize > 8*inttype->size || p->bitsize < 0) {
error("`%d' is an illegal bit-field size\n",
p->bitsize);
p->bitsize = 8*inttype->size;
} else if (p->bitsize == 0 && id) {
warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id);
p->name = stringd(genlabel(1));
}
p->lsb = 1;
}
else {
if (id == NULL)
error("field name missing\n");
else if (isfunc(p->type))
error("`%t' is an illegal field type\n", p->type);
else if (p->type->size == 0)
error("undefined size for field `%t %s'\n",
p->type, id);
}
if (isconst(p->type))
ty->u.sym->u.s.cfields = 1;
if (isvolatile(p->type))
ty->u.sym->u.s.vfields = 1;
n++;
if (Aflag >= 2 && n == 128)
warning("more than 127 fields in `%t'\n", ty);
if (t != ',')
break;
t = gettok();
}
test(';', stop);
} }
{ int bits = 0, off = 0, overflow = 0;
Field p, *q = &ty->u.sym->u.s.flist;
ty->align = IR->structmetric.align;
for (p = *q; p; p = p->link) {
int a = p->type->align ? p->type->align : 1;
if (p->lsb)
a = unsignedtype->align;
if (ty->op == UNION)
off = bits = 0;
else if (p->bitsize == 0 || bits == 0
|| bits - 1 + p->bitsize > 8*unsignedtype->size) {
off = add(off, bits2bytes(bits-1));
bits = 0;
chkoverflow(off, a - 1);
off = roundup(off, a);
}
if (a > ty->align)
ty->align = a;
p->offset = off;
if (p->lsb) {
if (bits == 0)
bits = 1;
if (IR->little_endian)
p->lsb = bits;
else
p->lsb = 8*unsignedtype->size - bits + 1
- p->bitsize + 1;
bits += p->bitsize;
} else
off = add(off, p->type->size);
if (off + bits2bytes(bits-1) > ty->size)
ty->size = off + bits2bytes(bits-1);
if (p->name == NULL
|| !('1' <= *p->name && *p->name <= '9')) {
*q = p;
q = &p->link;
}
}
*q = NULL;
chkoverflow(ty->size, ty->align - 1);
ty->size = roundup(ty->size, ty->align);
if (overflow) {
error("size of `%t' exceeds %d bytes\n", ty, inttype->u.sym->u.limits.max.i);
ty->size = inttype->u.sym->u.limits.max.i&(~(ty->align - 1));
} }
}
static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt) {
int i, n;
Symbol *callee, *caller, p;
Type rty = freturn(ty);
if (isstruct(rty) && rty->size == 0)
error("illegal use of incomplete type `%t'\n", rty);
for (n = 0; params[n]; n++)
;
if (n > 0 && params[n-1]->name == NULL)
params[--n] = NULL;
if (Aflag >= 2 && n > 31)
warning("more than 31 parameters in function `%s'\n", id);
if (ty->u.f.oldstyle) {
if (Aflag >= 1)
warning("old-style function definition for `%s'\n", id);
caller = params;
callee = newarray(n + 1, sizeof *callee, FUNC);
memcpy(callee, caller, (n+1)*sizeof *callee);
enterscope();
assert(level == PARAM);
while (kind[t] == STATIC || istypename(t, tsym))
decl(dclparam);
foreach(identifiers, PARAM, oldparam, callee);
for (i = 0; (p = callee[i]) != NULL; i++) {
if (!p->defined)
callee[i] = dclparam(0, p->name, inttype, &p->src);
*caller[i] = *p;
caller[i]->sclass = AUTO;
caller[i]->type = promote(p->type);
}
p = lookup(id, identifiers);
if (p && p->scope == GLOBAL && isfunc(p->type)
&& p->type->u.f.proto) {
Type *proto = p->type->u.f.proto;
for (i = 0; caller[i] && proto[i]; i++) {
Type ty = unqual(proto[i]);
if (eqtype(isenum(ty) ? ty->type : ty,
unqual(caller[i]->type), 1) == 0)
break;
else if (isenum(ty) && !isenum(unqual(caller[i]->type)))
warning("compatibility of `%t' and `%t' is compiler dependent\n",
proto[i], caller[i]->type);
}
if (proto[i] || caller[i])
error("conflicting argument declarations for function `%s'\n", id);
}
else {
Type *proto = newarray(n + 1, sizeof *proto, PERM);
if (Aflag >= 1)
warning("missing prototype for `%s'\n", id);
for (i = 0; i < n; i++)
proto[i] = caller[i]->type;
proto[i] = NULL;
ty = func(rty, proto, 1);
}
} else {
callee = params;
caller = newarray(n + 1, sizeof *caller, FUNC);
for (i = 0; (p = callee[i]) != NULL && p->name; i++) {
NEW(caller[i], FUNC);
*caller[i] = *p;
if (isint(p->type))
caller[i]->type = promote(p->type);
caller[i]->sclass = AUTO;
if ('1' <= *p->name && *p->name <= '9')
error("missing name for parameter %d to function `%s'\n", i + 1, id);
}
caller[i] = NULL;
}
for (i = 0; (p = callee[i]) != NULL; i++)
if (p->type->size == 0) {
error("undefined size for parameter `%t %s'\n",
p->type, p->name);
caller[i]->type = p->type = inttype;
}
if (Aflag >= 2 && sclass != STATIC && strcmp(id, "main") == 0) {
if (ty->u.f.oldstyle)
warning("`%t %s()' is a non-ANSI definition\n", rty, id);
else if (!(rty == inttype
&& (n == 0 && callee[0] == NULL
|| n == 2 && callee[0]->type == inttype
&& isptr(callee[1]->type) && callee[1]->type->type == charptype
&& !variadic(ty))))
warning("`%s' is a non-ANSI definition\n", typestring(ty, id));
}
p = lookup(id, identifiers);
if (p && isfunc(p->type) && p->defined)
error("redefinition of `%s' previously defined at %w\n",
p->name, &p->src);
cfunc = dclglobal(sclass, id, ty, &pt);
cfunc->u.f.label = genlabel(1);
cfunc->u.f.callee = callee;
cfunc->u.f.pt = src;
cfunc->defined = 1;
if (xref)
use(cfunc, cfunc->src);
if (Pflag)
printproto(cfunc, cfunc->u.f.callee);
if (ncalled >= 0)
ncalled = findfunc(cfunc->name, pt.file);
labels = table(NULL, LABELS);
stmtlabs = table(NULL, LABELS);
refinc = 1.0;
regcount = 0;
codelist = &codehead;
codelist->next = NULL;
if (!IR->wants_callb && isstruct(rty))
retv = genident(AUTO, ptr(unqual(rty)), PARAM);
compound(0, NULL, 0);
definelab(cfunc->u.f.label);
if (events.exit)
apply(events.exit, cfunc, NULL);
walk(NULL, 0, 0);
exitscope();
assert(level == PARAM);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -