diff options
| author | Michael Forney <mforney@mforney.org> | 2019-05-14 01:56:21 -0700 | 
|---|---|---|
| committer | Michael Forney <mforney@mforney.org> | 2019-05-14 01:56:21 -0700 | 
| commit | 8b21975e8221668eababac73aece15fda47c2f7c (patch) | |
| tree | edd08ba803f1bb3fb340098e66f5b90de170090b /decl.c | |
| parent | 5e7d36dd4ca41e5d3cae1e0025badbc72adfc516 (diff) | |
| download | cproc-8b21975e8221668eababac73aece15fda47c2f7c.tar.xz | |
decl: Factor out some code common to function and object declarations
Diffstat (limited to 'decl.c')
| -rw-r--r-- | decl.c | 117 | 
1 files changed, 59 insertions, 58 deletions
| @@ -775,6 +775,58 @@ typename(struct scope *s, enum typequal *tq)  	return t.type;  } +static enum linkage +getlinkage(enum declkind kind, enum storageclass sc, struct decl *prior, bool filescope) +{ +	if (sc & SCSTATIC) +		return filescope ? LINKINTERN : LINKNONE; +	if (sc & SCEXTERN || kind == DECLFUNC) +		return prior ? prior->linkage : LINKEXTERN; +	return filescope ? LINKEXTERN : LINKNONE; +} + +static struct decl * +declcommon(struct scope *s, enum declkind kind, char *name, struct type *t, enum typequal tq, enum storageclass sc, struct decl *prior) +{ +	struct decl *d; +	enum linkage linkage; +	const char *kindstr = kind == DECLFUNC ? "function" : "object"; + +	if (prior) { +		if (prior->linkage == LINKNONE) +			error(&tok.loc, "%s '%s' with no linkage redeclared", kindstr, name); +		linkage = getlinkage(kind, sc, prior, s == &filescope); +		if (prior->linkage != linkage) +			error(&tok.loc, "%s '%s' redeclared with different linkage", kindstr, name); +		if (!typecompatible(t, prior->type) || tq != prior->qual) +			error(&tok.loc, "%s '%s' redeclared with incompatible type", kindstr, name); +		prior->type = typecomposite(t, prior->type); +		return prior; +	} +	if (s->parent) +		prior = scopegetdecl(s->parent, name, true); +	linkage = getlinkage(kind, sc, prior, s == &filescope); +	if (linkage != LINKNONE && s->parent) { +		/* XXX: should maintain map of identifiers with linkage to their declaration, and use that */ +		if (s->parent != &filescope) +			prior = scopegetdecl(&filescope, name, false); +		if (prior && prior->linkage != LINKNONE) { +			if (prior->kind != kind) +				error(&tok.loc, "'%s' redeclared with different kind", name); +			if (prior->linkage != linkage) +				error(&tok.loc, "%s '%s' redeclared with different linkage", kindstr, name); +			if (!typecompatible(t, prior->type) || tq != prior->qual) +				error(&tok.loc, "%s '%s' redeclared with incompatible type", kindstr, name); +			t = typecomposite(t, prior->type); +		} +	} +	d = mkdecl(kind, t, tq, linkage); +	scopeputdecl(s, name, d); +	if (kind == DECLFUNC || linkage != LINKNONE || sc & SCSTATIC) +		d->value = mkglobal(name, linkage == LINKNONE); +	return d; +} +  bool  decl(struct scope *s, struct func *f)  { @@ -787,9 +839,8 @@ decl(struct scope *s, struct func *f)  	struct param *p;  	char *name;  	int allowfunc = !f; -	struct decl *d; +	struct decl *d, *prior;  	enum declkind kind; -	enum linkage linkage;  	uint64_t c;  	int align; @@ -823,52 +874,20 @@ decl(struct scope *s, struct func *f)  		t = qt.type;  		tq = qt.qual;  		kind = sc & SCTYPEDEF ? DECLTYPE : t->kind == TYPEFUNC ? DECLFUNC : DECLOBJECT; -		d = scopegetdecl(s, name, false); -		if (d && d->kind != kind) +		prior = scopegetdecl(s, name, false); +		if (prior && prior->kind != kind)  			error(&tok.loc, "'%s' redeclared with different kind", name);  		switch (kind) {  		case DECLTYPE:  			if (align)  				error(&tok.loc, "typedef '%s' declared with alignment specifier", name); -			if (!d) +			if (!prior)  				scopeputdecl(s, name, mkdecl(DECLTYPE, t, tq, LINKNONE)); -			else if (!typesame(d->type, t) || d->qual != tq) +			else if (!typesame(prior->type, t) || prior->qual != tq)  				error(&tok.loc, "typedef '%s' redefined with different type", name);  			break;  		case DECLOBJECT: -			if (d) { -				if (d->linkage == LINKNONE) -					error(&tok.loc, "object '%s' with no linkage redeclared", name); -				if (!(sc & SCEXTERN)) { -					linkage = f ? LINKNONE : sc & SCSTATIC ? LINKINTERN : LINKEXTERN; -					if (d->linkage != linkage) -						error(&tok.loc, "object '%s' redeclared with different linkage", name); -				} -				if (!typecompatible(d->type, t) || d->qual != tq) -					error(&tok.loc, "object '%s' redeclared with incompatible type", name); -				d->type = typecomposite(t, d->type); -			} else { -				if (sc & SCEXTERN) { -					if (s->parent) -						d = scopegetdecl(s->parent, name, true); -					linkage = d && d->linkage != LINKNONE ? d->linkage : LINKEXTERN; -					d = scopegetdecl(&filescope, name, false); -					if (d) { -						if (d->linkage != linkage) -							error(&tok.loc, "object '%s' redeclared with different linkage", name); -						if (!typecompatible(d->type, t) || d->qual != tq) -							error(&tok.loc, "object '%s' redeclared with incompatible type", name); -						t = typecomposite(t, d->type); -					} -				} else { -					linkage = f ? LINKNONE : sc & SCSTATIC ? LINKINTERN : LINKEXTERN; -				} - -				d = mkdecl(kind, t, tq, linkage); -				scopeputdecl(s, name, d); -				if (linkage != LINKNONE || sc & SCSTATIC) -					d->value = mkglobal(name, linkage == LINKNONE); -			} +			d = declcommon(s, kind, name, t, tq, sc, prior);  			if (d->align < align)  				d->align = align;  			if (consume(TASSIGN)) { @@ -916,25 +935,7 @@ decl(struct scope *s, struct func *f)  						error(&tok.loc, "old-style function definition does not declare '%s'", p->name);  				}  			} -			if (d) { -				if (!typecompatible(t, d->type) || tq != d->qual) -					error(&tok.loc, "function '%s' redeclared with incompatible type", name); -				d->type = typecomposite(t, d->type); -			} else { -				if (s->parent) -					d = scopegetdecl(s->parent, name, 1); -				if (d && d->linkage != LINKNONE) { -					linkage = d->linkage; -					if (!typecompatible(t, d->type) || tq != d->qual) -						error(&tok.loc, "function '%s' redeclared with incompatible type", name); -					t = typecomposite(t, d->type); -				} else { -					linkage = sc & SCSTATIC ? LINKINTERN : LINKEXTERN; -				} -				d = mkdecl(kind, t, tq, linkage); -				d->value = mkglobal(name, false); -				scopeputdecl(s, name, d); -			} +			d = declcommon(s, kind, name, t, tq, sc, prior);  			if (tok.kind == TLBRACE) {  				if (!allowfunc)  					error(&tok.loc, "function declaration not allowed"); | 
