📄 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 + -