⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decl.c

📁 LCC4.2 C编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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(&registers, 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 + -